2、React之Class component组件this的指向

94 阅读2分钟

1、为什么React中Class component组件中this需要进行bind()

      React官网上基本概念之事件处理里明确指出:This is not React-specific behavior; it is a part of how functions work in javascript(这是由于js函数的运行机制所决定的).但是,这仍会使很多刚接触React的开发者感到困惑。其实,如果需要理解这句话,那么首先需要理解ES6 class的部分特征与复杂类型的引用赋值。

     (1)class里定义的方法是定义在实例对象的原型对象(prototype)上的;

     (2)class里块级作用于里的代码,默认是strict模式的;

     (3)对于const fun1 = object.fun2; 这句话,仅仅是将object里属性名为fun2的函数的堆地址赋值给fun1,后面fun1如何调用,与object一点关系都没有;

     如果理解了以上三点,在结合下面代码的 1)-> 2) -> 3), 那就一目了然了。

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // (1) This binding is necessary to make `this` work in the callback   
    // 右侧this.handleClick为实例调用prototype上的方法,然后绑定this为实例自己
     	this.handleClick = this.handleClick.bind(this);  
    }

  handleClick() { 
  	// (3) 即未bind下,this.setState中this = undefined
  	this.setState(state => ({      
  		isToggleOn: !state.isToggleOn    
  	}));  
  }
  render() {
    return (
    /* 	(2) 对于onClick = this.handleClick,仅仅是函数赋值 在浏览器环境下onClick引用的函数被调用,
        这个函数里面的this若不绑定元素自身,则strict模式下为undefined,而class内代码为默认严格模式 */
      <button onClick={ this.handleClick }>        
      	{ this.state.isToggleOn ? 'ON' : 'OFF' }
      </button>
    );
  }
}

ReactDOM.render(
  <Toggle />,
  document.getElementById('root')
);

2)对于使用箭头函数的方式,那就需要理解另外一点:

     (4)箭头函数自身没有this绑定,其函数体里的this取决于词法作用于;对于在class里定义的箭头函数,其函数体里的this等于class里的this,即指向实例对象。理解了这句话,那么不论是使用 handleClick = () {},还是onClick={() => this.handleClick}其本质都是箭头函数的this取决于词法作用域。

    (1) public class fields syntax

 class LoggingButton extends React.Component {
  // This syntax ensures `this` is bound within handleClick.  
  // Warning: this is *experimental* syntax.  
  handleClick = () => {    
  	// class环境中定义的箭头函数里的this指向实例
  	console.log('this is:', this);  
  }
  
  render() {
    return (
      <button onClick={ this.handleClick }>
        Click me
      </button>
    );
  }
} 

(2) 箭头函数里返回一个函数

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // This syntax ensures `this` is bound within handleClick
    return (
    // 本质是箭头函数中this属于词法作用于,在编译时就已经确定
      <button onClick={() => this.handleClick()}>
        Click me
      </button>
    );
  }
}