你真的了解 React 事件吗?

609 阅读2分钟

React 事件基础

React中的事件是包装过的,事件冒泡是根据虚拟DOM树来冒泡的,与真实的DOM树无关。

在React中,事件本质上是React元素的一个属性。传递的是函数本身,而不是函数调用

React内置的组件(如button等)会在合适的时机,调用onClick等属性传递的参数。

自定义的组件,虽然设置了onClick属性,但是却没有在自定义组件中,将onClick属性运用到具体的React元素中,所以不会执行dom的默认事件。

在事件处理函数中,如果没有特殊处理,this指向undefined.

在事件处理函数中,处理this,你必须谨慎对待 JSX 回调函数中的 this,在 JavaScript 中,class 的方法默认不会 绑定 this。如果你忘记绑定 this.handleClick 并把它传入了 onClick,当你调用这个函数的时候 this 的值 为 undefined。

  • 使用bind。
    class Test extends Component {
    
        constructor(props) {
            super(props);
            // 绑定this到实例
            this.handleClick = this.handleClick.bind(this);
        }
    
        handleClick() {console.log('点击事件');}
    
        render() {
            return (
                // 绑定this到实例
                <div onClick={this.handleClick.bind(this)}/>
            );
        }
    }
    
  • 使用箭头函数
    class Test extends Component {
    
        // handle不在原型上,而是在对象上,this指向函数定义处
        handleClick = () => {
            console.log('点击事件');
        };
    
        render() {
            return (
                // 绑定this到实例
                <div onClick={() => {
                    console.log('点击事件');
                }}>
    
                </div>
            );
        }
    }
    

React 事件进阶

这里的事件:React内置的DOM组件中的事件

  1. 给document注册事件
  2. 几乎所有的元素的事件处理,均在document的事件中处理
    1. 一些不冒泡的事件,是直接在元素上监听
    2. 一些document上面没有的事件,直接在元素上监听
  3. 在document的事件处理,React会根据虚拟DOM树的完成事件函数的调用
  4. React的事件参数,并非真实的DOM事件参数,是React合成的一个对象,该对象类似于真实DOM的事件参数
    1. stopPropagation,阻止事件在虚拟DOM树中冒泡
    2. nativeEvent,可以得到真实的DOM事件对象
    3. 为了提高执行效率,React使用事件对象池来处理事件对象

注意事项

  1. 如果给真实的DOM注册事件,阻止了事件冒泡,则会导致react的相应事件无法触发
  2. 如果给真实的DOM注册事件,事件会先于React事件运行
  3. 通过React的事件中阻止事件冒泡,无法阻止真实的DOM事件冒泡
  4. 可以通过nativeEvent.stopImmediatePropagation(),阻止document上剩余事件的执行
  5. 在事件处理程序中,不要异步的使用事件对象,如果一定要使用,需要调用persist函数