React事件处理函数绑定this的集中方法
目前React有三种方法可以创建组件,其中使用React.createClass()函数创建的组件,this会自动
绑定到组件的每个方法中;而使用Class Component或者Functional Component时,需要手动绑定this.
1. 在构造函数中绑定
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
2.使用class properties进行绑定
class properties目前处于state-2草案阶段,babel已经支持
class LoggingButton extends React.Component {
// This syntax ensures `this` is bound within handleClick.
// Warning: this is *experimental* syntax.
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
3. 使用箭头函数
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
);
}
}
这种方式有一个潜在的性能问题,就是每次组件渲染时,onClick的回调函数都是不同的匿名函数,如果这个组件把回调函数通过props传递到其子组件,那么由于每次组件的渲染时,由于传递的props中回调函数的变化,就会导致子组件的额外渲染(是不同的回调函数,但实际上处理逻辑完全相同)。
4. 使用bind()
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={this.handleClick.bind(this)}>
Click me
</button>
);
}
}
bind跟使用箭头函数一样,实际上每次组件渲染时都生成了新的回调函数。
建议使用构造函数中绑定或者使用class properties特性绑定,但bind和箭头函数在特殊场景下需要使用,即需要传递额外参数的情况。
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>