[译]React核心概念5:事件处理

原文连接:reactjs.org/docs/handli…html

事件处理函数

处理React元素的事件与处理DOM元素上的事件十分类似,它们仅有一些语法上的区别。react

  • React事件名采用小驼峰命名规则而不是纯小写
  • 使用JSX须要传入函数做为事件处理函数而不是传入字符串

例如,在HTML上浏览器

<button onclick="activateLasers()">
  Activate Lasers
</button>
复制代码

在React中则略微不一样bash

<button onClick={activateLasers}>
  Activate Lasers
</button>
复制代码

React上的另外一个不一样之处在于你不能返回false去阻止默认行为,必须显示地调用preventDefault才能阻止默认行为。函数

在HTML中,为了阻止锚点连接默认打开一个新页面能够这样写:性能

<a href="#" onclick="console.log('The link was clicked.'); return false">
  Click me
</a>
复制代码

可是在React中,须要这样写才能阻止打开新页面:ui

function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The link was clicked.');
  }

  return (
    <a href="#" onClick={handleClick}>
      Click me
    </a>
  );
}
复制代码

在这里,e是一个合成事件。React根据W3C规范来定义这些合成事件,因此无需担忧浏览器的兼容问题。this

使用React时,一般不须要调用addEventListener来为已建立的DOM元素添加监听器。取而代之的是在元素被渲染之初提供一个监听器。spa

当你定义了一个ES6 class组件时,一个经常使用的方法是将事件处理器声明为class的一个方法。下面的代码声明了一个Toggle组件,让用户能在ON和OFF两种状态之间切换。prototype

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // 这段代码让this在回调函数中可以有效
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(state => ({
      isToggleOn: !state.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

ReactDOM.render(
  <Toggle />,
  document.getElementById('root')
);
复制代码

必须谨慎对待JSX回调函数中的this,在Javascript中,class方法是不会默认绑定this的。若是你忘记绑定this.handleClick并将它传递给onClick,那么当这个方法被调用时浏览器将没法识别this,由于此时thisundefined

这不是React特有的特性,这与JavaScript的工做原理相关。一般来讲,若是不在方法后面加上(),好比onClick={this.handleClick},咱们就应该绑定它。

若是以为绑定方法很麻烦,这里有两种选择能够避免绑定。若是你正在使用实验性的public class fields语法,你可使用class fields正确绑定回调。

class LoggingButton extends React.Component {
  // 这个语法能够确保回调函数已经绑定了this
  // 但请注意这是实验性的语法
  handleClick = () => {
    console.log('this is:', this);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}
复制代码

这种语法在使用Create React App建立的项目中是可使用的。

若是没有使用class fields语法,那么你能够在回调函数中使用箭头函数。

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // 这段代码确保了handleClick绑定了this
    return (
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
    );
  }
}
复制代码

可是这个语法有一个问题,每当LoggingButton被渲染时都会建立一个不一样回调函数。在大多数状况下这是没有问题的,可是若是这个回调函数做为props传递给子组件时,这些组件可能会作一个额外的从新渲染。因此咱们一般推荐在构造函数中绑定事件或者使用class fields语法来绑定以免此类的性能问题。

向事件处理函数传递参数

在循环中咱们一般须要传递一个额外的参数给事件处理函数。好比若是id时想要删除的那一行的id,如下两种方法均可以将id传递给事件处理函数。

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
复制代码

上面两行代码是等价的,只不过度别使用了箭头函数Function.prototype.bind

在上面的两个例子中,合成事件e表明了React事件,都做为第二个参数传递给事件处理函数。在箭头函数中咱们须要显示地传递e,可是使用bind方法,事件对象以及更多的参数都被隐式地传递。

相关文章
相关标签/搜索