在React中,事件是组件与用户或其他组件通信的重要方式,例如:点击按钮、输入文本、拖动元素等。事件绑定是指将事件处理函数与组件的某个属性或元素关联起来,以便在事件发生时执行相应的逻辑。
React事件绑定有很多种方式,每种方式都有其优缺点,本文将介绍四种常用的事件绑定方法,并比较它们的区别和使用场景
<button onclick="clickHandle()">提交</button>
<script>
function clickHandle(e){
e.preventDefault(); //阻止默认事件
//或者使用如下的写法
return false;
}
</script>
<button onClick={clickHandle}>提交</button>
<script>
function clickHandle(e){
e.preventDefault(); //阻止默认事件,不能使用return false
}
</script>
在回调函数中使用箭头函数,直接在render()里写行内的箭头函数(不推荐),这种写法存在的问题就是:当每次执行render()的时候就会创建一个不同的回调函数。在大多数情况下,这是没有问题的。然而如果这个回调函数作为一个属性值传入低阶组件,这些组件可能会进行额外的重新渲染
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class Box extends Component {
handleClick(e,val){
console.log(e,val);
}
render() {
return (
<button onClick={(e)=>this.handleClick(e,'aa')}>添加</button>
);
}
}
ReactDOM.render(
<Box />,
document.getElementById('root')
);
使用属性初始化器来正确的绑定回调函数(推荐),在组件内使用箭头函数定义一个方法
优点: 简单易懂,不需要使用bind方法,可以避免每次渲染时创建新的函数实例。
缺点: 类成员函数语法需要在构造函数中进行支持。
适用场景: 适用于处理简单的事件逻辑,组件树比较浅。
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class Box extends Component {
handleClick =(e)=>{
console.log(e);
}
render() {
return (
<button onClick={this.handleClick}>添加</button>
);
}
}
ReactDOM.render(
<Box />,
document.getElementById('root')
);
在render()方法肿,使用bind绑定this(不推荐)。直接在组件定义一个非箭头函数的方法,然后再render里直接使用onClick={this.handleClick.bind(this)}
优点: 代码简单易懂,容易理解。
缺点: 每次渲染都会创建一个新的函数实例,可能会影响性能。
适用场景: 适用于处理简单的事件逻辑,组件树比较浅,需要绑定this。
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class Box extends Component {
handleClick(val,e) { //事件对象e要放在最后
console.log(val,e);
}
render() {
return (
<button onClick={this.handleClick.bind(this, 'aa')}>添加</button>
);
}
}
ReactDOM.render(
<Box />,
document.getElementById('root')
);
直接在组件内定义一个非箭头函数的方法,然后再constructor里bind(this)(推荐)
优点: 避免在每次渲染时都创建一个新的函数实例,提高性能。
缺点: 代码比较繁琐。
适用场景: 适用于处理复杂的事件逻辑,需要绑定this。
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class Box extends Component {
constructor(){
super();
this.myhandleClick = this.handleClick.bind(this);
}
handleClick(e){
console.log(e);
}
render() {
return (
<button onClick={this.myhandleClick}>添加</button>
);
}
}
ReactDOM.render(
<Box />,
document.getElementById('root')
);
和普通浏览器一样,事件 handleClick 会被自动传入一个 event 对象,这个对象和普通的浏览器 event 对象所包含的方法和属性都基本一致。不同的是 React中的 event 对象并不是浏览器提供的,而是它自己内部所构建的。它同样具有event.stopPropagation、event.preventDefault 这种常用的方法。
<button onClick={(e)=>this.handleClick(e, 'aa')}>添加</button>
<button onClick={this.handleClick.bind(this, 'aa')}>添加</button>
值得注意的是,通过 bind 方式向监听函数传参,在类组件中定义的监听函数,事件对象 e 要排在所传递参数的后面。
在子组件中修改父组件传过来的参数,比较推荐的方法是, 在父组件中定义方法,子组件中调用父组件的方法,通过props传递到子组件中,然后在子组件中通过this.props.method来调用。看下面的例子:
class Button extends Component {
handleClick(){
//执行DOM元素的 change属性
this.props.change();
}
render() {
return (
<button onClick={()=>this.handleClick()}>
{this.props.children}
</button>
);
}
}
class Counter extends Component {
constructor() {
super();
this.state = {
count: 0
}
}
handleChange(type) {
this.setState((preState, props) => {
count: preState.count + 1
}
}, () => { })
}
render() {
return (
<div >
<Button change={() => this.handleChange()}>-</Button>
</div>
);
}
}
React中的事件绑定提供了多种选择,使开发人员能够选择最适合他们的方式。使用addEventListener方法、React事件系统或第三方库,都可以实现事件绑定。选择哪种方式取决于开发者的个人偏好和项目需求。