美文网首页
7.事件冒泡和事件捕获(同一个DOM元素,注册两个事件,一个冒泡

7.事件冒泡和事件捕获(同一个DOM元素,注册两个事件,一个冒泡

作者: solo2016 | 来源:发表于2016-11-15 21:28 被阅读0次

    这个问题的整理是基于面试题:
    给同一个DOM元素绑定两个事件,一个用冒泡,一个用捕获,会执行几次?先执行冒泡还是先执行捕获?

    例子:

    <div id="outer"> 
        <p id="inner">Click me!</p>
    </div>
    

    事件冒泡:

    微软提出了名为事件冒泡(event bubbling)的事件流。事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象。
    因此上面的例子在事件冒泡的概念下发生click事件的顺序应该是p -> div -> body -> html -> document

    事件捕获:

    网景提出另一种事件流名为事件捕获(event capturing)。与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。
    上面的例子在事件捕获的概念下发生click事件的顺序应该是document -> html -> body -> div -> p

    如下代码,有四个div嵌套元素,均绑定了click事件,addEventListener函数的第三个参数设置为false说明不为捕获事件,即为冒泡事件。该代码执行结果如下:
    点击one元素,输出one;
    点击two元素,输出two one;
    点击three元素,输出 three two one;
    点击four元素,输出 four three two one;

    <div id='one'>
            <div id='two'>
                <div id='three'>
                    <div id='four'>
                    </div>
                </div>
            </div>
        </div>
    <script>
    
        var one=document.getElementById('one');
        var two=document.getElementById('two');
        var three=document.getElementById('three');
        var four=document.getElementById('four');
    
        one.addEventListener('click',function(){
            alert('one');
        },false);
        two.addEventListener('click',function(){
            alert('two');
        },false);
        three.addEventListener('click',function(){
            alert('three');
        },false);
        four.addEventListener('click',function(){
            alert('four');
        },false);
    </script>
    

    而捕获则相反。当触发目标元素时,会从目标元素的最顶层的祖先元素事件往下执行到目标元素为止。
    将上面的代码第三个参数均改为true,则执行结果如下:
    点击one,输出one;
    点击two,输出one two;
    点击three,输出one two three;
    点击four,输出one two three four;
    很明显执行顺序是不同的。

    问题解释:

    无论是冒泡事件还是捕获事件,元素都会先执行捕获阶段
    从上往下,如有捕获事件,则执行;一直向下到目标元素后,从目标元素开始向上执行冒泡元素

    如下代码:
    此时点击four元素,four元素为目标元素,one为根元素祖先,从one开始向下判断执行。
    one为捕获事件,输出one;
    two为冒泡事件,忽略;
    three为捕获时间,输出three;
    four为目标元素,开始向上冒泡执行,输出four;(从此处分为两部分理解较容易。)
    three为捕获已执行,忽略;
    two为冒泡事件,输出two;
    one为捕获已执行,忽略。
    最终执行结果为:one three four two

    one.addEventListener('click',function(){
            alert('one');
        },true);
        two.addEventListener('click',function(){
            alert('two');
        },false);
        three.addEventListener('click',function(){
            alert('three');
        },true);
        four.addEventListener('click',function(){
            alert('four');
        },false);
    

    执行次数:绑定了几个事件便执行几次。

    如下代码,two元素绑定了两个不同事件,点击two都会执行这两个事件。而执行顺序有所差异
    1、如果two为目标元素,目标元素的事情按顺序执行,而其他元素根据W3C的标准执行,即先捕获后冒泡。
    点击two执行结果:one(因为是two的父元素支持捕获事件所以先执行) two,bubble two,capture(顺序执行,注意逗号不是间隔,是输出内容。)
    2、如果目标元素不是two,则two的两个事件按先捕获后冒泡触发执行,也就是跟前面讨论的执行过程是一样的,只不过两个事件都绑定在同一个DOM元素上。
    点击three执行结果:one two,capture three,capture two,bubble

    one.addEventListener('click',function(){
            alert('one');
        },true);
        two.addEventListener('click',function(){
            alert('two,bubble');
        },false);
        two.addEventListener('click',function(){
            alert('two,capture');
        },true);
        three.addEventListener('click',function(){
            alert('three,capture');
        },true);
        four.addEventListener('click',function(){
            alert('four,capture');
        },true);
    

    相关文章

      网友评论

          本文标题:7.事件冒泡和事件捕获(同一个DOM元素,注册两个事件,一个冒泡

          本文链接:https://www.haomeiwen.com/subject/gielpttx.html