learn
learn copied to clipboard
React 事件处理
React 是如何处理事件的
React 的事件是合成事件, 内部原理非常复杂,我这里只把关键性,可以用来解答这个问题的原理部分进行介绍即可。
jsx 实际上是 React.createElement(component, props, …children)
函数提供的语法糖,那么这段 jsx 代码:
<button onClick={this.handleClick}>Click me</button>
会被转化为:
React.createElement(
"button",
{
onClick: this.handleClick
},
"Click me"
);
React 在组件加载(mount)和更新(update)时,将事件通过 addEventListener 统一注册到 document 上,然后会有一个事件池存储了所有的事件,当事件触发的时候,通过 dispatchEvent 进行事件分发。
所以你可以简单的理解为,最终 this.handleClick
会作为一个回调函数调用。
四种事件处理对比
对于事件处理的写法也有好几种,咱们来进行对比一下:
- 直接 bind this 型
就是像文章开始的那样,直接在事件那里 bind this
class Foo extends React.Component {
handleClick() {
this.setState({ xxx: aaa });
}
render() {
return <button onClick={this.handleClick.bind(this)}>Click me</button>;
}
}
优点:写起来顺手,一口气就能把这个逻辑写完,不用移动光标到其他地方。
缺点:性能不太好,这种方式跟 react 内部帮你 bind 一样的,每次 render 都会进行 bind,而且如果有两个元素的事件处理函数式同一个,也还是要进行 bind,这样会多写点代码,而且进行两次 bind,性能不是太好。(其实这点性能往往不会是性能瓶颈的地方,如果你觉得顺手,这样写完全没问题)
- constuctor 手动 bind 型
class Foo extends React.Component {
constuctor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({ xxx: aaa });
}
render() {
return <button onClick={this.handleClick}>Click me</button>;
}
}
优点:相比于第一种性能更好,因为构造函数只执行一次,那么只会 bind 一次,而且如果有多个元素都需要调用这个函数,也不需要重复 bind,基本上解决了第一种的两个缺点。
缺点:没有明显缺点,硬要说的话就是太丑了,然后不顺手(我觉得丑,你觉得不丑就这么写就行了)。
- 箭头函数型
class Foo extends React.Component {
handleClick() {
this.setState({ xxx: aaa });
}
render() {
return <button onClick={e => this.handleClick(e)}>Click me</button>;
}
}
优点:顺手,好看。
缺点:每次 render 都会重复创建函数,性能会差一点。
- public class fields 型
class Foo extends React.Component {
handleClick = () => {
this.setState({ xxx: aaa });
};
render() {
return <button onClick={this.handleClick}>Click me</button>;
}
}
优点:好看,性能好。
缺点:没有明显缺点,如果硬要说可能就是要多装一个 babel 插件来支持这种语法。
学习资料:新手学习 react 迷惑的点(二)