为什么事件处理程序没有得到正确的处理?

时间:2017-02-27 18:14:42

标签: javascript reactjs ecmascript-6

我理解绑定事件处理程序的概念,以便他们获得对this的正确引用。我的问题是,为什么引用一个类的方法没有提供正确的this

ES6类是否不会自动为类方法提供this

class MyComponent extends Component {
  clickHandler(event) {
    console.log('this', this);
  }

  render() {
    return <button onClick={this.clickHandler}>Button</button>;
  }
}

正如预期的那样,上面的代码将打印null以获取this的值。但是,显式调用处理程序将给出正确的值,即<button onClick={event => this.clickHandler(event)} />。为什么处理程序使用箭头函数对this有正确的引用?

我可以假设一堆答案,但我喜欢正确的答案。

1 个答案:

答案 0 :(得分:1)

  

为什么事件处理程序没有得到正确的处理?

他们这样做!正常情况下,他们会引用您挂钩事件的元素。

  

ES6类是否不会自动为类方法提供this

他们没有,没有; ES2015(“ES6”)类使用与ES5及之前相同的基本原型继承和this赋值,具有不同的语法(以及一些新功能)。

  

但是,显式调用处理程序将给出正确的值

是的,出于同样的原因,在此代码中,使用example调用this来引用x

x.example();

...但在此代码中,调用examplethisundefined(在严格模式下;它将是松散模式下的全局对象):

let e = x.example;
e();

使用class并不会改变对this管理的需求。

要使this引用组件类,您需要将this绑定到它,或者使用关闭this的箭头函数来使用:

绑定(一种相当常见的模式):

class MyComponent extends Component {
  constructor(...args) {                               // ***
    super(...args);                                    // ***
    this.clickHandler = this.clickHandler.bind(this);  // ***
  }                                                    // ***

  clickHandler(event) {
     console.log('this', this);
  }

  render() {
    return <button onClick={this.clickHandler}>Button</button>;
  }
}

使用箭头功能(也很常见):

class MyComponent extends Component {

  clickHandler = event => {                            // ***
     console.log('this', this);
  };                                                   // ***

  render() {
    return <button onClick={this.clickHandler}>Button</button>;
  }
}

后一种选择假设您正在转发支持即将到来的public class fields,这些尚未标准化。 (截至撰写本文时,该提案在still处为stage 2。)不是在原型上创建属性,而是创建一个带箭头函数的实例字段,该函数关闭this(其中是对组件实例的引用。