React元素处理事件和DOM元素处理事件非常相像。有些语法上的差异:
·React事件使用camelCase(驼峰),而不是lowercase(小写)命名。
·在JSX中你传递一个方法作为事件处理器,而不是字符串。
例如,下面的HTML:
<button οnclick="activateLasers()">
Activate Lasers
</button>
相较于React有明显不同:
<button onClick={activateLasers}>
Activate Lasers
</button>
另一个不同是在React中你不能通过返回false来阻止默认行为。你必须明确地调用preventDefault。用简单的HTML,要阻止打开新网页的默认链接行为,你可以这样写:
<a href="#" οnclick="console.log('The link was clicked'); return false">Click me </a>
在React中,这个应该替代成:
function ActionLink(){
function handleClick(e){
e.preventDefault();
console.log('The link was clicked.');
}
return(
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
这里的e是一个合成的事件。React依照W3C spec定义这些合成的事件,因此你不必担心浏览器兼容性。看合成事件的参考指南学习更多。当使用React时,你通常不需要调用addEventListener给已创建的DOM元素增加监听器。相反,在元素被初始渲染的时候,就可以提供一个监听器了。
当你用ES6类定义一个组件时,一个事件通常的处理方式是类中的一个方法。例如,Toggle组件定义一个让用户切换ON和OFF状态的按钮:
class Toggle extends React.Component{
constructor(props){
super(props);
this.state={isToggleOn:true};
//This binding is necessary to make 'this' work in the callback
this.handleClick=this.handleClick.bind(this);
}
render(){
<button onClick={this.handleClick}>
{this.state.isToggleOn?'ON':'OFF'}
</button>
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
}
在CodePen上试试吧。
在JSX callbacks中你必须注意this的含义。在JavaScript中,类方法不会默认绑定。如果你忘记绑定this.handleClick并将它传递给OnClick,当函数实际被调用时,this将是undefined。
这不是React特有的行为;它是函数如何在JavaScript中运行的一部分。一般,涉及到不带()的方法,例如onClick={this.handleClick},你应该绑定这个方法。
如果调用困扰到你,以下有两种解决办法。如果你正在使用试验性的属性初始化语法,你可以使用属性初始化正确绑定调用:
class LoggingButton extends React.Component{
//This syntax ensures 'this' is bound within handleClick.
//Warning:this is * experimental * syntax.
handleClick=()=>{
console.log('this is:',this);
}
render(){
return(
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
这个语法在Create React App中默认被使用。
如果你不使用属性初始化语法,你可以在调用中使用箭头函数:
class LoggingButtonn extends React.Component{
handleClick(){
console.log('this is:',this);
}
render(){
//This syntax ensures 'this' is bound within handleClick
return(
<button onClick={(e)=>this.handleClick(e)}>
Click me
</button>
);
}
}
使用这种语法的问题是每次LoggingButton渲染时,一个不同的回调被创建。大部分情况下,还好。然而,回调作为属性传递给低级组件(子组件),这些组件可能做一个扩展重新渲染。我们通常推荐在构造函数中绑定或者使用属性初始化语法,避免这种性能问题。