React事件绑定以及参数传递

2019年10月29日Web前端

事件是JS中重要的组成部分,在React中,内置了他自己的一套绑定和处理事件的逻辑,我们来看下这几种模式下的参数设置与获取以及他们的优缺点。

由于自定义的类方法没有绑定this,所以需要我们手动去绑定,才可以正确的去调用。

React事件绑定方式

1. constructor中bind绑定

class IndexPage extends React.Component{
  constructor(props) {
    super(props)

    this.event1 = this.event1.bind(this)
  }

  event1() {
    console.log('event1');
  }

  render() {
    return (
      <button onClick={ this.event1 }>event1</button>
    );
  }
}

该方式提前在构造函数中绑定this,不需要在使用再次改变this。当然该方式在没有state的情况下,需要额外写constructor函数。

2. 调用时箭头函数绑定

class IndexPage extends React.Component{
  event2() {
    console.log('event2');
  }

  render() {
    return (
      <button onClick={ () => { this.event2() } }>event2</button>
    );
  }
}

利用ES6中的箭头函数this的特性,仅在使用时进行this绑定。

3. 调用时bind绑定

class IndexPage extends React.Component{
  event3() {
    console.log('event3');
  }

  render() {
    return (
      <button onClick={ this.event3.bind(this) }>event3</button>
    );
  }
}

和前一种方式一样,在使用时绑定,但是和前者一样,在每次调用时,会新生成一个方式实例,如果接受参数的是组件的话,会引起额外的渲染,造成对性能的影响。

4. ES6箭头函数初始化

class IndexPage extends React.Component{
  event4 = () => {
    console.log('event4');
  }

  render() {
    return (
      <button onClick={ this.event4 }>event4</button>
    );
  }
}

利用箭头函数在创建时绑定了this,当然该方式需要babel转义。

函数传参

函数事件的使用中,参数也是个重要的角色。我们来看下这几种方式下如何进行参数的传递。

首先,将这几个函数整合到一个页面中:

class IndexPage extends React.Component{
  constructor(props) {
    super(props)

    this.event1 = this.event1.bind(this, 1);
  }

  event1(a, e) {
    console.log('event1', a, e);    // 1 {}
  }
  event2(a, e) {
    console.log('event2', a, e);    // 2 {}
  }
  event3(a, e) {
    console.log('event3', a, e);    // 3 {}
  }
  event4 = (e) => {
    console.log('event4', e);       // {}
  }

  render() {
    return (
      <div>
        <button onClick={ this.event1 }>event1</button>
        <button onClick={ (e) => { this.event2(2, e) } }>event2</button>
        <button onClick={ this.event3.bind(this, 3) }>event3</button>
        <button onClick={ this.event4 }>event4</button>
      </div>
    );
  }
}
  • event1方式可以在bind时传入自定义的参数,在最后会补上event参数。
  • event2方式由于显示的传参,所以他需要显示的传入event参数。
  • event3方式同event1一致,但是可以传入在render中获取或计算后的参数。
  • event4方式没法传入自定义参数,但是event参数是可以拿到的。

event参数丢失

直接使用event参数时没有太大的问题,但是在setTimeout中使用时,获取到了null,并有一个warning在控制台上显示。

The SyntheticEvent is pooled. This means that the SyntheticEvent object will be reused and all properties will be nullified after the event callback has been invoked. This is for performance reasons. As such, you cannot access the event in an asynchronous way.

所以,我们可以提前先保存event上的一些简单数据,比如:

let val = event.target.value

这样就可以了。

总结

由于event2和event3方式是在使用时返回event实例,对性能有影响,所以在没有参数要传时不建议使用,又由于event1需要额外写代码,所以推荐使用event4这种方式。

当需要传如参数时,固定的参数区分不同函数时可以使用event1,其他方式event2或event3都可以。

详细的demo可见:github