learn icon indicating copy to clipboard operation
learn copied to clipboard

React 事件处理

Open yangtao2o opened this issue 4 years ago • 0 comments

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 迷惑的点(二)

yangtao2o avatar Apr 14 '20 04:04 yangtao2o