事件处理

我们需要在constructor中对于事件与对应的handler函数进行绑定.

大多数时候我们在发出DOM事件的组件内部写我们的handler函数.
在下面的例子中,我们在组件内部创建了一个click handler, 因为我们想所有的Swithcer Component当被点击时,做出同样的响应.

  1. class Switcher extends React.Component {
  2. render() {
  3. return (
  4. <button onClick={ this._handleButtonClick }>
  5. click me
  6. </button>
  7. );
  8. }
  9. _handleButtonClick() {
  10. console.log('Button is clicked');
  11. }
  12. }

上面这样做完全没有问题,因为_handleButtonClick是一个函数, 我们把这个函数和onClick这个React支持的event绑定在了一起.

但是上面这样做也会带来问题, 使用function的写法, 会在function初始化时生成一个this. 比如我们在_handleButtonClick里面使用this, 此时的this是_handleButtonClick生成出来的, 和Switcher这个class的this没有任何关系, 如果我想访问类似于this.props 或者 this.state这样的对象, 代码便会报错.

  1. class Switcher extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.state = { name: 'React in patterns' };
  5. }
  6. render() {
  7. return (
  8. <button onClick={ this._handleButtonClick }>
  9. click me
  10. </button>
  11. );
  12. }
  13. _handleButtonClick() {
  14. console.log(`Button is clicked inside ${ this.state.name }`);
  15. // 将导致
  16. // Uncaught TypeError: Cannot read property 'state' of null
  17. }
  18. }

所以我们常用的解决办法像下面一样使用bind

  1. <button onClick={ this._handleButtonClick.bind(this) }>
  2. click me
  3. </button>

然而, 这种写法意味这我们要一次又一次的去调bind函数, 因为我们的button可能会被渲染很多次.
一种更好的做法是在组件的constructor中去做我们bind函数的调用.

  1. class Switcher extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.state = { name: 'React in patterns' };
  5. this._buttonClick = this._handleButtonClick.bind(this);
  6. }
  7. render() {
  8. return (
  9. <button onClick={ this._buttonClick }>
  10. click me
  11. </button>
  12. );
  13. }
  14. _handleButtonClick() {
  15. console.log(`Button is clicked inside ${ this.state.name }`);
  16. }
  17. }

另一种办法是使用箭头函数建立我们的handler函数, 因为箭头函数并不会创建this.

顺带一提的是, Facebook也推荐使用这种方法去处理需要访问组件的this的函数.

但是, 在constructor中去做binding也同样有用处. 比如, 我们可能会将父组件中定义的函数作为Props传下去. 因此在子组件中, 我们需要对这个函数进行bind.