react组件中事件处理的几种写法,几种写法的区别,bind(this)传自定义的参数

react组件中事件处理的几种写法,几种写法的区别,bind(this)传自定义的参数

一、在React元素绑定事件要注意的两点
  1. 在React中事件的命名要采用驼峰命名法,而不是原生dom中的小写,如:onclick要写成onClick, onchange 要写成onChange
  2. 响应事件的函数要以对象的形式赋值,而不是以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问题的全部内容,如有不当,欢迎指正

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容