06/19 10:30
相关文章
React 中文文档 - 事件处理
JavaScript Private and Public Class Fields
关于React事件回调函数bind(this)
函数作为React组件的方法时, 箭头函数和普通函数的区别是什么?
事件处理函数的 this
React 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:
使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。
例如,传统的 HTML:
<button onclick="handleClick()">
click me!
</button>
在 React 中略微不同:
<button onClick={handleClick}>
click me!
</button>
我们的期望是,点击事件发生时,传入的函数的 this 就绑定在定义的类上。
但实际上,等到点击事件发生,函数被调用时,它已经丢失了我们所期望的 this 的绑定。实际上此时的 this 是默认绑定,即,this 的指向在非严格模式下默认是全局作用域,在严格模式下是 undefined。
所以,我们需要对事件处理函数,进行显式的 this 绑定。
显式绑定 this 的方法
1. 在 HTML 的 onclick 中绑定
在 onclick 中绑定有两种写法:使用 bind 或箭头函数。
例如:
/* bind 绑定 */
<button onClick={this.handleClick.bind(this)}></button>
/* 箭头函数绑定 */
<button onClick={(e) => this.handleClick(e)}></button>
这种写法难看不说,问题在于每次渲染时都会创建不同的回调函数。在大多数情况下,这没什么问题,但如果该回调函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。
使用这种写法,每次的组件渲染都会重新计算 this.handleClick.bind(this)
或 (e) => this.handleClick(e)
。这意味着,每次传给子组件的 props.onClick 实际上都是不同的。这种对象会变化但实际内容并无变化的 props,会对子组件的 shouldComponentUpdate 优化造成影响。
这是因为 React 提供了 shouldComponentUpdate 让开发者能够控制避免不必要的 render,还提供了在 shouldComponentUpdate 自动进行 Shallow Compare 的 React.PureComponent。 继承自 PureComponent 的组件只要 props 和 state 中的值不变,组件就不会重新 render。
然而如果用了上述写法,每次父组件渲染,传给子组件的 props.onClick 都会变,PureComponent 的 Shallow Compare 基本上就失效了。
因此,并不推荐使用这两种写法来绑定事件处理函数的 this。
2. 在 React 元素中绑定
在 React 元素中绑定也有两种写法:手动在 constructor 中使用 bind 绑定,或使用 Public Class Fields 写法。
例如,手动在 constructor 中使用 bind 绑定:
constructor(props) {
super(props);
// 为了在回调中使用 this,这个绑定是必不可少的
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
click me!
</button>
);
}
每次都在构造器中手动 bind 绑定是一件很繁琐的事情,有时候还会忘记,导致严重的后果。为了简便,更推荐使用 Public Class Fields 写法。
Public Class Fields 写法:
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
click me!
</button>
);
}
使用 class fields 正确的绑定回调函数,可以省去不必要的 constructor,简化代码。
总结
- 为 React 元素指定事件处理函数时,不要忘记绑定它的 this
- 建议使用 Public Class Fields 写法以优化性能与代码