react组件中事件处理的几种写法,几种写法的区别,bind(this)传自定义的参数
一、在React元素绑定事件要注意的两点
- 在React中事件的命名要采用驼峰命名法,而不是原生dom中的小写,如:onclick要写成onClick, onchange 要写成onChange
- 响应事件的函数要以对象的形式赋值,而不是以dom字符串的形式,如:
//在 dom中:
<button onclick="clickMe()">不服点我</button>
//在React中
<button onClick={clickButton}>不服点我</button> //clickButton是一个函数
注意:React的事件是合成事件,并不是原生的dom事件,在dom中可以通过返回false来阻止事件的默认行为,但是在react中必须显示调用事件对象的e.preventDefault来阻止事件的默认行为,除了这一点之外,和原生的事件并无差别
二、在React中事件处理函数主要的三中写法,不同的写法解决this指向问题的方式也不同,性能也有差异,具体如下:
1. 使用es6的箭头函数
class MyComponent extends React.Component{
constructor(){
super(props);
this.state = {
number:0
}
}
render(){
<button onClick={(e)=>{console.log(this.state.number);}}>不服点我</button>
}
}
分析,此时this指向的是函数定义时所在的对象,所以this总是指向当前组件的实例,不足是当前的组件逻辑比较复杂时,把组件的逻辑写在{}内会导致render的臃肿,不容易比较直观的看出UI的结构,同时代码的可读性也不会很好,解决方法为把逻辑封装为组件的一个方法,然后在函数中调用这个方法:
class MyComponent extends React.Component{
constructor(){
super(props);
this.state = {
number:0
}
}
handleClick(e){
const number = ++this.state.number;
this.setState({
number
});
};
render(){
<button onClick={(e)=>this.handleClick(e);}>不服点我</button>
}
注意,直接在render中定义事件处理函数的最大的问题就是,每次render调用的时候都会创建一个新的事件处理函数,给组件带来额外的开销,当组件的层级越低,开销就越大,组件上的任何上一层级组件的变化都会触发这个组件的render方法(一般可以忽略)。
2.使用组件的方法
直接将组件的方法赋值给这个事件的元素,同时在构造函数中将这个方法的this绑定到当前对象,如:
class MyComponent extends React.Component{
constructor(){
super(props);
this.state = {
number:0
}
this.handleClick = this.handleClick.bind(this);
}
handleClick(e){
const number = ++this.state.number;
this.setState({
number
});
};
render(){
<button on click={this.handleClick}>不服点我</button>
}
这种方法的好处是每次渲染都不会重新创建一个回调函数,没有额外的性能损失;
但是,如果在一个组件中有很多的事件函数时,这种在构造函数中绑定this的方法就会比较繁琐,所以还可以直接在给事件属性直接赋值时绑定this;
class MyComponent extends React.Component{
constructor(){
super(props);
this.state = {
number: 0
}
}
handleClick(e){
const number = ++this.state.number;
this.setState({
number
});
}
render(){
<div>{this.state.number}</div>
<button onClick={this.handleClick.bind(this)}>点我</button>
}
}
分析:
(1)缺点: 此方法在每次render时都会重新创建一个函数,在性能上有所损失;
(2)优点: 事件处理函数需要传参数时,这个方法比较好,看下面的例子
class MyComponent extends React.Component{
constructor(){
super(props);
this.state = {
list: [1, 2, 3, 4, 5],
current: 1
}
}
//每点击一项,将点击项设置为当前项,所以需要将点击项作为参数传递
handleClick(item, e){
this.setState({
current: item
});
}
render(){
let { list } = this.state;
return (
<ul>
{
(!!list && list.length>0) && list.map((listItem, index)=>{
return <li onClick={this.handleClick.bind(this, listItem)}>{listItem}</li>
})
}
</ul>
)
}
}
3. 属性初始化语法(property initializer syntax)
使用es7的属性初始化语法会自动为class中的定义的方法绑定this,例如:
class MyComponent extends React.Component{
constructor(){
super(props);
this.state = {
number: 0
}
}
handleClick = (e)=>{
const number = ++this.state.number;
this.setState({
number
});
}
render(){
<div>{this.state.number}</div>
<button onClick={this.handleClick}>点我</button>
}
}
优点:此种方法既不用担心在构造函数中绑定this,非常繁琐;
也不用担心在渲染时重复生成函数,造成性能问题
这个还处在实验性阶段,默认不支持,但是官方的脚手架 creat-react-app 默认支持;如果你要是想在项目中使用,你可以在项目中引入babel 的 transform-class-properties 插件获取这个特性的支持。
以上为react事件处理的三种方式以及this问题的全部内容,如有不当,欢迎指正