javascript - 事件冒泡与事件捕获的先后问题?
伊谢尔伦
伊谢尔伦 2017-04-10 17:18:39
[JavaScript讨论组]

我看资料上说现代浏览器对于事件冒泡与事件捕获都是支持的。我写了如下代码:

        <p id="p1">
            <p id="p2">
                <input id="btn1" type="button"  value="按钮"/>
            </p>
        </p>
        <script type="text/javascript">
            var p1 = document.getElementById("p1");
            var p2 = document.getElementById("p2");
            var btn = document.getElementById("btn1");
            
            p1.addEventListener("click",function ( event ) {
                console.log("p1,false");
            },false)
            p2.addEventListener("click",function ( event ) {                
                console.log("p2,false");
            },false)
            btn.addEventListener("click",function ( event ) {                
                console.log("btn,false");
            },false)
            p1.addEventListener("click",function ( event ) {                
                console.log("p1,true");
            },true)
            p2.addEventListener("click",function ( event ) {                
                console.log("p2,true");
            },true)
            btn.addEventListener("click",function ( event ) {                
                console.log("btn,true");
            },true)
            
        </script>

然后我在 Chrome和 Safari浏览器中运行的结果都是一样的。如下图:

问题来了:为什么Btn的click事件顺序和p是相反的?

伊谢尔伦
伊谢尔伦

小伙看你根骨奇佳,潜力无限,来学PHP伐。

全部回复(2)
黄舟

1). 事件处理其实有3个阶段:事件捕获阶段、事件目标阶段、事件冒泡阶段
2). 先从根节点向下执行捕获回调函数,一直到实际触发事件的元素的父元素位置,捕获过程结束;
3). 然后事件传播到实际触发事件的DOM元素上,为事件目标阶段,这个阶段有个地方要注意:

>For event listeners attached to the event target; the event is in the target phase, rather than capturing and bubbling phases. Events in the target phase will trigger all listeners on an element regardless of the useCapture parameter.
>在事件目标阶段,无论addEventListener函数第3个参数指定的时true还是false,绑定的回调函数都会被执行

4). 然后冒泡阶段开始,执行触发事件的DOM节点上的回调函数,然后继续向上执行冒泡阶段的回调函数,一直到根节点
5). 事件的执行顺序按事件回调函数的添加顺序执行

所以执行顺序为
p1->p2 捕获阶段
->btn1,false 目标阶段先添加的
->btn1,true 目标阶段后添加的
p2->p1 冒泡阶段

如果把添加的事件顺序修改一下

    p1.addEventListener("click",function ( event ) {
                console.log("p1,false");
    },false)
    p2.addEventListener("click",function ( event ) {                
        console.log("p2,false");
    },false)
    btn.addEventListener("click",function ( event ) {                
        console.log("btn,true");
    },true)
    p1.addEventListener("click",function ( event ) {                
        console.log("p1,true");
    },true)
    p2.addEventListener("click",function ( event ) {                
        console.log("p2,true");
    },true)
    btn.addEventListener("click",function ( event ) {                
        console.log("btn,false");
    },false);

那么执行的顺序为
p1->p2 捕获阶段
->btn1,true 目标阶段先添加的
->btn1,false 目标阶段后添加的
p2->p1 冒泡阶段

PHPz

在一个前端群群友的帮助下解决了这个问题

意思就是事件流中 p1 -> p2 是捕获阶段,触发捕获阶段的监听器 然后事件流转到BTN 就进入目标阶段 该阶段没有冒泡和捕获之分 所以两个监听器按照绑定顺序先后触发。然后事件 ->p2 ->p1 这个阶段就是冒泡阶段 触发冒泡阶段的监听器

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号