React事件处理
React元素的事件处理和DOM元素的事件处理很相似。有下面的一些语法差异:
- React事件使用驼峰命名法而不是小写字母+“-”命名法
- 在JSX中传入函数表达式绑定事件而不是函数名称字符串
例如,在HTML中:
1 | <button onclick="activateLasers()"> |
在React中略有不同:
1 | <button onClick={activateLasers}> |
另一个区别是你不能返回false
来阻止React中的默认行为。您必须显式调用事件的preventDefault
方法。比如,在原生的HTML为了阻止默认的链接行为打开新页面,我们这么写:
1 | <a href="#" onclick="console.log('The link was clicked.'); return false"> |
在React中,应该是:
1 | function ActionLink() { |
这里,e
是一个合成事件。React根据W3C规范定义了这些合成事件,所以你不必担心跨浏览器兼容性。请参阅SyntheticEvent参考指南以了解更多信息。
当使用React时,通常不需要调用addEventListener
来在创建DOM元素之后添加事件监听器。相反,只需在元素初始渲染时提供一个侦听器。
当你定义一个ES6 class格式的组件时,一种常见的模式是把事件处理程序作为类中的一个方法。比如,这个Toggle
组件呈现一个按钮,让用户在“ON”和“OFF”状态之间切换:
1 | class Toggle extends React.Component { |
在JSX回调中,你必须this
的含义。在JavaScript中类方法默认是没有边界的。如果你在没有绑定this.handleClick
的情况下传递参数到onClick
的话,调用该函数时this
是undefined
。
这不是React特有行为,这是函数在js中的运行机制。通常如果你在引用一个方法时候方法名没有带()
,比如onClick={this.handleClick}
,你应该绑定该方法。
如果你觉得调用bind
方法来绑定函数麻烦,有两种解决这个问题的方法。如果你使用的是实验中的公共类字段语法,你可以使用类字段来正确地绑定回调:
1 | class LoggingButton extends React.Component { |
在Create React App中默认启用该语法。
如果你没有使用公共类字段语法,你可以在回调中使用一个箭头函数:
1 | class LoggingButton extends React.Component { |
这种语法的问题是当LoggingButton
每次渲染时都要创建一个不同的回调。大多数情况下,这没问题。但是如果回调函数是作为props传递给子组件的话,这些组件可能会做额外的重新渲染。我们通常建议在构造函数中绑定或使用类字段语法,以避免这种性能问题。
给事件处理函数传递参数
在循环内部,通常需要将一个额外的参数传递给事件处理程序。比如,如果id是行ID,则以下两种都可以工作:
1 | <button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button> |
上面两行代码是等价的,区别只是一个使用箭头函数一个使用函数原型链绑定。
在这两种情况下,代表React事件的参数e
会作为参数ID之后的第二个参数传递。使用箭头函数时,我们必须明确的传递e
,但是使用bind
时会自动转发。