React 事宜冒泡

在React中,我们能够在建立element的时刻,传入事宜和处置惩罚函数,这些事宜会被做为合成事宜来处置惩罚,固然,有些时刻,我们也须要定义原生事宜,比方给document绑定事宜。有些情况下,就须要经由过程阻挠事宜冒泡来完成预期的交互效果。下面是几个简朴的demo

Demo

比方有以下的代码:

import React from 'react'
class Demo1 extends React.Component{
    onClickInner(e){
        console.log('inner div')
    }
    onClickOuter(e){
        console.log('outer div')
    }
    render(){
        return <div onClick={this.onClickOuter}>
            <div onClick={this.onClickInner}>inner div</div>
        </div>
    }
}

当我们点击 inner div时,控制台输出效果:

inner div
outer div

这两个事宜都是合成事宜,在点击时,两个事宜会顺次冒泡到document,由一致的事宜监听器处置惩罚。如果愿望阻挠onClickOuter 触发,能够在onClickInner内挪用e.stopPropagation()。须要注重的是,这里的e是合成事宜实例,挪用stopPropagation 也只能阻挠合成事宜的冒泡。

如果我们将onClickOuter 经由过程原生事宜来绑定:

class App extends React.Component {
    onClickInner(e) {
        e.stopPropagation();
        console.log("inner div");
    }
    onClickOuter(e) {
        console.log("outer div");
    }
    componentDidMount() {
        this.outer.onclick = this.onClickOuter;// 经由过程DOM 0级绑定
    }
    render() {
        return (
            <div ref={ref => (this.outer = ref)}>
                <div id='inner' onClick={this.onClickInner}>123</div>
            </div>
        );
    }
}

虽然在onClickInner内挪用了 e.stopPropagation, 然则原生事宜照样会经由过程冒泡来触发,而且会先于onClickInner, 控制台输出:

outer div
inner div

这是由于onClickInner合成事宜被触发的时刻,申明点击事宜已经由过程冒泡通报到了document,在这个过程当中,便会经由外层的div,进而触发该原生事宜。这也申清楚明了,合成事宜的stopPropagation只能阻挠合成事宜的冒泡。纵然我们在这里经由过程e.nativeEvent获取到原生事宜并挪用stopPropagation,也杯水车薪,由于上面已说了,在该合成事宜被触发的时刻,已冒泡到了document.
那末我们该经由过程什么体式格局来阻挠原生事宜onClickOuter被触发呢:
既然在onClickInner处置惩罚不了,只能在onClickOuter内处置惩罚了:

onClickOuter(e) {// 这里e是原生事宜
   if(e.target && e.target.id === 'inner'){
       return ;
   }
   console.log("outer div");
}

如果我们将原生事宜绑定在了document上:

class App extends React.Component {
    constructor(props) {
        super(props);
        // this.bindDocument();
    }
    onClickInner(e) {
        console.log("inner div");
    }
    componentDidMount() {
        this.bindDocument();
    }
    bindDocument() {
        document.addEventListener("click", function(e) {
            console.log("document");
        });
    }
    render() {
        return (
            <div id="inner" onClick={this.onClickInner}>
                123
            </div>
        );
    }
}

上面代码中,在组件挂载终了后,再给document绑定click事宜,这时刻,React合成事宜已注册完成,当点击时,document上的click事宜会根据绑定递次的前后顺次实行,所以控制台会输出:

inner div
document

如果愿望阻挠后绑定的事宜触发,能够在onClickInner内挪用stopImmediatePropagation

如果有多个雷同范例事宜的事宜监听函数绑定到同一个元素,当该范例的事宜触发时,它们会根据被增加的递次实行。如果个中某个监听函数实行了 event.stopImmediatePropagation() 要领,则当前元素剩下的监听函数将不会被实行。

    原文作者:neove
    原文地址: https://segmentfault.com/a/1190000018728165
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞