原文连接:reactjs.org/docs/handli…html
处理React元素的事件与处理DOM元素上的事件十分类似,它们仅有一些语法上的区别。react
例如,在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
,由于此时this
是undefined
。
这不是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方法,事件对象以及更多的参数都被隐式地传递。