为什么以及何时我们需要在 React 中绑定函数和事件处理程序?

Why and when do we need to bind functions and eventHandlers in React?

class SomeClass extends Component{
  someEventHandler(event){
  }
  render(){
    return <input onChange={------here------}>
  }
}

我看到 ------here------ 部分的不同版本。

// 1
return <input onChange={this.someEventHandler.bind(this)}>

// 2
return <input onChange={(event) => { this.someEventHandler(event) }>

// 3
return <input onChange={this.someEventHandler}>

版本有何不同?还是只是偏好问题?


感谢大家的回答和评论。所有这些都是有帮助的,如果你和我一样对此感到困惑,我强烈建议阅读这篇 link FIRST
http://blog.andrewray.me/react-es6-autobinding-and-createclass/

为什么要绑定一个 React 函数?

当您使用 ES6 class 定义组件时,一个常见的模式是事件处理程序是 class 上的一个方法。在JavaScript中,class方法默认不绑定。如果你忘记了bind this.someEventHandler而把它传给了onChange,那么当函数真正被调用时,这将是未定义的。

一般来说,如果你引用的方法后面没有(),比如onChange={this.someEventHandler},你应该绑定那个方法。

可以通过三种方式将 onChange 函数绑定到正确的上下文

第一

return <input onChange={this.someEventHandler.bind(this)}>

在这一个中,我们明确地使用 bind 来使 onChange 事件作为 eventHandler 的参数可用。我们还可以发送一些其他语法类型的参数,如

return <input onChange={this.someEventHandler.bind(this, state.value)}>

第二

return <input onChange={(event) => { this.someEventHandler(event) }>

这是 ES6 语法,我们可以通过它指定要传递给 someEventHandler 函数的参数。这相当于 .bind(this) 然而,它也让我们可以灵活地随事件一起发送其他属性,例如

return <input onChange={(event, value) => { this.someEventHandler(event, value) }>

第三

使用箭头函数定义函数 someEventHandler

someEventHandler = () => {
    console.log(this); // now this refers to context of React component
}

arrow function 没有自己的 this,使用封闭执行上下文的 this 值,因此上述函数获得正确的上下文。

在构造函数中绑定它

constructor(props) {
   super(props);
   this.someEventHandler = this.someEventHandler.bind(this);
}


return <input onChange={this.someEventHandler}>

在此方法中,事件直接附加到 someEventHandler 函数。不能通过这种方式传递其他参数

绑定不是 React 特有的东西,而是 this 在 Javascript 中的工作方式。每个函数/块都有自己的上下文,因为函数更具体到它的调用方式。在添加 ES6 支持时(class语法)。

何时绑定上下文取决于函数的用途,如果您需要访问 class 上的道具、状态或其他成员,则需要绑定它。

对于您的示例,每个都是不同的,这取决于您的组件的设置方式。

预绑定到您的 class

.bind(this) 用于将 this 上下文绑定到您的组件函数。但是,它 returns 每个渲染周期都会引用一个新函数!如果您不想绑定函数的每次使用(例如在点击处理程序中),您可以预先绑定该函数。

a. 在构造函数中进行绑定。又名

class SomeClass extends Component{
    constructor(){
        super();
        this.someEventHandler = this.someEventHandler.bind(this);
    }
    someEventHandler(event){
    }
    ....
} 

b. 在 class 粗箭头函数上创建自定义函数。又名

class SomeClass extends Component{
    someEventHandler = (event) => {
    }
    ....
}

运行时绑定到您的 class

执行此操作的几种常用方法

a. 您可以使用内联 lambda(粗箭头)函数包装您的组件处理函数。

onChange={ (event) => this.someEventHandler(event) }

这可以提供额外的功能,比如如果您需要为点击处理程序传递额外的数据 <input onChange={(event) => { this.someEventHandler(event, 'username') }>bind

也可以这样做

b. 你可以使用 .bind(this) 如上所述。

onChange={ this.someEventHandler.bind(this) }

带有附加参数 <input onChange={ this.someEventHandler.bind(this, 'username') }>

如果您想避免创建新的函数引用但仍需要传递参数,最好将其抽象为子组件。

在你的例子中

// 1
return <input onChange={this.someEventHandler.bind(this)}>

这只是将运行时事件处理程序绑定到您的 class。

// 2
return <input onChange={(event) => this.someEventHandler(event) }>

另一个运行时绑定到您的 class。

// 3
return <input onChange={this.someEventHandler}>

您只是将函数作为回调函数传递给点击事件发生时触发,没有额外的参数。确保预先绑定它!

总结一下。考虑如何优化您的代码是件好事,每种方法都有一个实用程序/目的,具体取决于您的需要。