React元素的事件处理和DOM元素类似。但是有一点语法上的不同:
- React事件绑定属性的命名采用驼峰式写法,而不是小写
- 如果采用JSX的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM元素的写法)
HTML通常写法是:React中写法为:1
2
3<botton onclick="acticateLasers()">
激活按钮
</button>React中另一个不同是你不能使用返回false的方式阻止默认行为,你必须明确使用1
2
3<button onClick={activateLsers}>
激活按钮
</button>proventDefault
.
例如,通常我们在HTML中阻止链接默认打开一个新页面,可以这样写。React中的写法为1
2
3<a href="#" onclick="console.log('点击链接');return false">
点我
</a>实例中e是一个合成事件。1
2
3
4
5
6
7
8
9
10
11
12function ActionLink(){
function handleClick(e){
e.preventDefault();
console.log('链接被点击');
}
return (
<a href="#" onClick={handleClick}>
点我
</a>
);
}
使用React的时候通常你不需要使用addEventListener为一个已创建的DOM元素添加监听器。你仅仅需要在这个元素初始渲染的时候提供一个监听器。
当你使用ES6 class语法来定义一个组件的时候,事件处理器会成为类的一个方法,例如,下面的Toggle组件渲染一个让用户切换开关状态的按钮:你必须谨慎对待JSX回调函数中的this,类的方法默认不会绑定this的。如果你忘记绑定this.handleClick并把它传入onClick,当你调用这个函数的时候this的值会是undefinde.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27class Toglle extends React.Component{
constructor(props){
super(props);
super(props);
this.state = {isToggleOn: true};
//这边绑定是必要的,这样`this`才能在回调函数中使用
this.handleClick = this.handleClick.bing(this);
}
handleClick(){
this.setState(prevState=>({
isToggleOn: !prevState.isToggleOn
}));
}
render(){
return(
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' :'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('example')
);
并不是React的特殊行为,他是函数如何在JacaScript中运行的一部分,通常情况下,如果你没有在方法后面添加(),例如onClick={this.handleClick}
,你应该为这个方法绑定this.
如果使用bind让你很烦,这里有两种方法可以解决,如果你正在使用实验性的属性初始化器语法,你可以使用属性初始化器来让你正确的绑定回调函数如果你没有使用属性初始化器语法,你可以在回调函数中使用箭头函数:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class LoggingButton extends React.Component{
//这个语法确保了'this'绑定在handleClick中
//这里只是一个测试
handleClik = () => {
console.log('this is:',this);
}
render(){
return(
<botton onClick={this.handleClick}>
Click me
</botton>
);
}
}使用这个语法有个问题就是每次LoggingButton渲染的时候都会创建一个不同的回调函数。在大多数情况下,这没有问题,然而如果这个回调函数作为一个属性值传入低阶组件,这些组件可能会进行额外的重新渲染。我们通常建议在构造函数中绑定或者使用属性初始化器来避免这些性能问题。1
2
3
4
5
6
7
8
9
10
11
12
13class LogginButton extends React.Component{
handleClick(){
console.log('this is:',this);
}
render(){
//这个语法确保了`this`绑定在handleClick中
return (
<button onClick={(e) => this.handleClick(e)}>Click me
</button>
);
}
}向事件处理程序传递参数
通常我们会为事件处理程序传递额外的参数。例如,若是ID是你要删除的那一行的id,以下两种方式都可以向事件处理程序传递参数:上述两种方式都是等价的1
2<button onClink={(e) => this.deleteRow(id,e)}>Delete Row</button>
<button onClink={this.deleteRow.bing(this,id)}>Delete Row</button>
上面两个例子中,参数e作为React事件对象将会被作为第二个参数进行传递。通过箭头函数的方式,事件对象必须显式的进行传递,但是通过bind的方式,事件对象以及更多的参数将会被隐式的进行传递。
指的注意的是,通过bind方式向监听函数传参,在类组件中定义的监听函数,事件对象e要排在所传递参数的后面,例如1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21class Popper extends React.Component{
constructor(){
super();
this.state={name:'Hello World!'};
}
preventPop(name,e){ //事件对象e要放到最后
e.preventDefault();
alert(name);
}
render(){
return(
<div>
<p>hello</p>
{/*通过bing()方法传递参数。*/}
<a href="https://reactjs.org" onClick={this.preventPop.bind(this,this.state.name)}>Click</a>
</div>
);
}
}