React事件处理

Posted 橘猫吃不胖~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React事件处理相关的知识,希望对你有一定的参考价值。

React事件处理

1 React事件处理

React与DOM事件处理的不同之处:
(1)React事件的命名方式是小驼峰方式,DOM的命名方式是小写。例如:DOM的命名:onclick,React的命名:onClick。
(2)事件处理函数是以对象的方式赋值,而不是以字符串的方式赋值。例如:DOM以字符串方式:onclick = "handleClick()",React以对象方式:onClick = handleClick
(3)阻止默认事件的方式不同。DOM通过返回false来阻止:<a href="www.baidu.com" onclick="javascript:return false;">百度</a>,React需要显式调用e.preventDefault来阻止。

2 React中事件处理函数

2.1 使用ES6的箭头函数

1、在render函数中使用箭头函数

示例代码:点击按钮,在终端输出0

    <div id="root"></div>
    <script type="text/babel">
        // 获取div
        let root = document.getElementById("root");
        // 创建类组件
        class MyComponent extends React.Component 
            constructor(props) 
                super(props);
                this.state =  // 定义状态机
                    number: 0
                
            
            render() 
                return (
                    <div>
                        /* this指向当前组件的实例 */
                        <button onClick=(event) => console.log(this.state.number)>点击</button>
                    </div>
                )
            
        
        // 渲染
        ReactDOM.render(<MyComponent />, root);
    </script>

优点:不用在构造函数中绑定this
缺点:当函数的逻辑比较复杂时,render就显得臃肿,无法直观的看到组件的UI结构,代码可读性差

2、使用class fields语法:将箭头函数赋给类的属性

示例代码:点击按钮在终端输出click

    <div id="root"></div>
    <script type="text/babel">
        // 获取div
        let root = document.getElementById("root");
        // 创建类组件
        class MyComponent extends React.Component 
            constructor(props) 
                super(props);
            
            handleClick = () => 
                console.log("click");
            
            render() 
                return (
                    <button onClick=this.handleClick>点击</button>
                )
            
        
        // 渲染
        ReactDOM.render(<MyComponent />, root);
    </script>

优点:不用在构造函数中绑定this,在render函数中调用简单

2.2 在constructor函数中bind

在构造函数中进行绑定:将事件处理函数作为类的成员函数
注意:在定义事件处理函数时,是无法识别this(即this是undefined的),必须在构造函数中绑定this

示例代码:点击按钮,在终端输出click

    <div id="root"></div>
    <script type="text/babel">
        // 获取div
        let root = document.getElementById("root");
        // 创建类组件
        class MyComponent extends React.Component 
            constructor(props) 
                super(props);
                // 将事件响应函数绑定到当前组件的实例上
                this.handleClick = this.handleClick.bind(this);
            
            // 编写事件响应函数
            handleClick() 
                console.log("click");
            
            render() 
                return (
                    // this.handleClick后面不加(),否则代表不点击直接调用
                    <button onClick=this.handleClick>点击</button>
                )
            
        
        // 渲染
        ReactDOM.render(<MyComponent />, root);
    </script>

优点:在render函数调用时不需要重新创建事件处理函数
缺点:当事件处理很多时,构造函数就显的很繁琐

2.3 在render函数中绑定this

示例代码:点击按钮,在终端输出click

    <div id="root"></div>
    <script type="text/babel">
        // 获取div
        let root = document.getElementById("root");
        // 创建类组件
        class MyComponent extends React.Component 
            constructor(props) 
                super(props);
            
            // 编写事件响应函数
            handleClick() 
                console.log("click");
            
            render() 
                return (
                    <button onClick=this.handleClick.bind(this)>点击</button>
                )
            
        
        // 渲染
        ReactDOM.render(<MyComponent />, root);
    </script>

优点:在调用事件处理函数时,传参比较方便
缺点:每次调用render函数时都重新绑定,导致性能下降

2.4 几种方式的比较

影响constroctor函数中bind使用class fields语法render中使用箭头函数在render中使用bind
render时生成新函数
性能无影响无影响有影响有影响
可直接携带参数
简洁性不好

3 事件处理中传参

3.1 直接传递参数

1、在构造函数中给事件处理函数绑定this,调用事件处理函数时直接传参
注:在箭头函数中调用事件处理函数时不需要绑定this

示例代码:点击张三按钮,终端输出编号1,点击李四按钮,终端输出编号2

    <div id="root"></div>
    <script type="text/babel">
        // 获取div
        let root = document.getElementById("root");
        // 创建类组件
        class MyComponent extends React.Component 
            constructor(props) 
                super(props);
                this.state = 
                    list: [
                        
                            id: 1,
                            name: "张三"
                        ,
                        
                            id: 2,
                            name: "李四"
                        
                    ]
                
                // 本例中该语句不需要,因为下面的箭头函数中已经绑定了this
                // this.handleClick = this.handleClick.bind(this);
            
            handleClick(id) 
                console.log("编号" + id)
            
            render() 
                // 获取状态属性值
                const  list  = this.state
                return (
                    <div>
                        
                            list.map((item) => <button onClick=() =>  this.handleClick(item.id) >item.name</button>)
                        
                    </div>
                )
            
        
        // 渲染
        ReactDOM.render(<MyComponent />, root);
    </script>


2、在render函数中调用事件处理函数时进行this的绑定

示例代码:点击张三按钮,终端输出编号1,点击李四按钮,终端输出编号2

    <div id="root"></div>
    <script type="text/babel">
        // 获取div
        let root = document.getElementById("root");
        // 创建类组件
        class MyComponent extends React.Component 
            constructor(props) 
                super(props);
                this.state = 
                    list: [
                        
                            id: 1,
                            name: "张三"
                        ,
                        
                            id: 2,
                            name: "李四"
                        
                    ]
                
                // 本例中该语句可以没有,因为下面的handleClick()函数中没有使用到this
                // this.handleClick = this.handleClick.bind(this);
            
            handleClick(id) 
                console.log("编号" + id)
            
            render() 
                // 获取状态属性值
                const  list  = this.state
                return (
                    <div>
                        
                            list.map((item) => <button onClick=this.handleClick.bind(this, item.id)>item.name</button>)
                        
                    </div>
                )
            
        
        // 渲染
        ReactDOM.render(<MyComponent />, root);
    </script>

3.2 使用data自定义属性

在定义UI控件时使用data自定义属性,在事件处理函数中通过“e.target.dataset.属性名”来获取UI控件中的data属性值

示例代码:点击张三按钮,终端输出编号1,点击李四按钮,终端输出编号2

    <div id="root"></div>
    <script type="text/babel">
        // 获取div
        let root = document.getElementById("root");
        // 创建类组件
        class MyComponent extends React.Component 
            constructor(props) 
                super(props);
                this.state = 
                    list: [
                        
                            id: 1,
                            name: "张三"
                        ,
                        
                            id: 2,
                            name: "李四"
                        
                    ]
                
            
            handleClick(e) 
                // 事件处理函数,e表示触发事件的对象
                console.log("编号" + e.target.dataset.count)
            
            render() 
                // 获取状态属性值
                const  list  = this.state
                return (
                    <div>
                        
                            list.map((item) => <button
                                onClick=this.handleClick.bind(this)
                                data-count=item.id // 标签的自定义属性使用“data-”开头,后面跟着自定义属性名
                            >item.name</button>)
                        
                    </div>
                )
            
        
        // 渲染
        ReactDOM.render(<MyComponent />, root);
    </script>

4 事件流

说明:
(1)React的事件流默认是冒泡
(2)React中使用捕获方式:事件类型后面加一个后缀Capture,例如:onClickCapture

示例:冒泡方式传递

    <div id="root"></div>
    <script type="text/babel">
        let root = document.getElementById('root')
        // 1.定义CSS样式
        const style = 
            child: 
                width: '100px',
                height: '100px',
                backgroundColor: 'red'
            ,
            parent: 
                width: '150px',
                height: '150px',
                backgroundColor: 'blue'
            ,
            ancestor: 
                width: '200px',
                height: '200px',
                backgroundColor: 'green'
            
        
        // 2.定义类组件
        class App extends React.Component 
            render() 
                return (
                    <div onClick=() =>  console.log("ancestor")  style=style.ancestor>
                        <div onClick=() =>  console.log("parent")  style=style.parent>
                            <div onClick=(e) => 
                                console.log("child");
                            
                                style=style.child>
                            </div>
                        </div>
                    </div>
                )
            
        
        //3.渲染
        ReactDOM.render(<App />, root)
    </script>

点击红色区域,按照child、parent、ancestor的顺序在终端输出。

示例:捕获方式传递

        // 2.定义类组件
        class App extends React.Component 
            render() 
                return (
                    <div onClickCapture=() =>  console.log("ancestor")  style=style.ancestor>
                        <div onClickCapture=() =>  console.log("parent")  style=style.parent>
                            <div onClickCapture=(e) => 
                                console.log("child");
                            
                                style=style.child>
                            </div>
                        </div>
                    </div>
                )
            
        

点击红色区域,按照ancestor、parent、child的顺序在终端显示。

5 事件委托

在合成事件系统中,所有事件都是绑定在document元素上,即,虽然我们在某个react元素上绑定了事件,但是,最后事件都委托给document统一触发。在合成事件中只能阻止合成事件中的事件传播

示例:基于上一部分的案例,阻止事件冒泡

        // 2.定义类组件
        class App extends React.Component 
            render() 
                return (
                    <div onClick=(e) =>  console.log("ancestor")  style=style.ancestor>
                        <div onClick=(e) =>  console.log("parent")  style=style.parent>
                            <div onClick=(e) => 
                                console.log("child");
                                e.stopPropagation(); // 阻止冒泡
                            
                                style=style.child>
                            </div>
                        </div>
                    </div>
                )
            
        

点击红色区域,只输出child,成功阻止了事件冒泡。

执行流程如下:

可以看到,react 阻止的事件流,并没有阻止真正DOM元素的事件触发,当红色div元素被点击时,真正的元素还是按照冒泡的方式,层层将事件交给上级元素进行处理,最后事件传播到document,触发合成事件,在合成事件中,child触发时,e.stopPropagation();被调用,合成事件中的事件被终止。因此,合成事件中的stopPropagation无法阻止事件在真正元素上的传递,它只阻止合成事件中的事件流。相反,如果我们在红色的div上,绑定一个真正的事件,那么,合成事件则会被终止。

6 事件对象

虽然React事件是合成事件,但是在事件处理中是<

以上是关于React事件处理的主要内容,如果未能解决你的问题,请参考以下文章

React 事件处理

React之事件处理

React事件处理及事件流

React事件处理及事件流

React事件处理及事件流

react之事件处理