深度剖析JavaScript中冒泡和捕获机制、事件代理

2023-12-17 19:02:34

?? JS事件传播的两种机制包括冒泡和捕获,下面将具体剖析它们之间本质的区别。


?? 事件冒泡: 先触发子元素的事件,再触发父元素的事件。


?? 创建一个 ul label 和 li label, 分别绑定一个父id 和 子 id, 再通过创建 script,去绑定各自的点击事件。



在这里插入图片描述



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <ul id="father">
        我是一个无序列表
        <li id="son">1个列表项</li>
    </ul>

    <script>
        document.getElementById('father').onclick = function(){
            console.log('我点击了父元素');
        }

        document.getElementById('son').onclick = function(){
            console.log('我点击了子元素');
        }

    </script>
</body>

</html>


?? 当我点击 "第1个列表项"后,在Console先输出的是 “我点击了子元素”, 然后是 “我点击了父元素”, 可见冒泡的执行顺序是由里向外,也就是从 li - ul - body - document - window 这样的执行顺序,就好比人扔了一块石头去河里,先是冒一个小泡,再逐个现成大的水泡这种扩散现象。因此,JS默认的点击事件就是冒泡。



在这里插入图片描述



?? 事件捕获: 先触发父元素的事件,再触发子元素的事件。如果要将冒泡改为捕获,需要添加监听事件。监听事件的第3个参数必须为 “true”, 默认为 false 。



在这里插入图片描述



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <ul id="father">
        我是一个无序列表
        <li id="son">1个列表项</li>
    </ul>

    <script>
        // document.getElementById('father').onclick = function(){
        //     console.log('我点击了父元素');
        // }

        document.getElementById('father').addEventListener('click',function(){
            console.log('我点击了父元素');
        },true);

        document.getElementById('son').onclick = function(){
            console.log('我点击了子元素');
        }

    </script>
</body>

</html>


? ? 再点击 "第1个列表项"后,控制台先输出的是 “我点击了父元素”, 然后是 “我点击了子元素”, 可见捕获的执行顺序是由外向里,也就是从 window - documment - body - ul - li 这样的执行顺序。



在这里插入图片描述



? ? 事件代理是指利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。


? ? 先复制多几个 li label



在这里插入图片描述



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <ul id="father">
        我是一个无序列表
        <li id="son">1个列表项</li>
        <li id="son">2个列表项</li>
        <li id="son">3个列表项</li>
        <li id="son">4个列表项</li>
        <li id="son">5个列表项</li>
    </ul>

    <script>
        // document.getElementById('father').onclick = function(){
        //     console.log('我点击了父元素');
        // }

        document.getElementById('father').addEventListener('click',function(){
            console.log('tesing for 事件代理');
        },true);

        // document.getElementById('son').onclick = function(){
        //     console.log('我点击了子元素');
        // }

    </script>
</body>

</html>


?? 例如然后点击 “第5个列表项”,由于冒泡作用,当点击到 li label,冒泡到 ul label 上,执行了 ul label上的点击事件,最后在 Console 输出了 “tesing for 事件代理”。



在这里插入图片描述



在这里插入图片描述



?? 通常父级那么多子元素,怎样去区分事件本应该是哪个子元素呢?在 function() 函数里面添加一个 event param, 稍后在Console打印这个 event 的 object



在这里插入图片描述



?? 例如当点击 “第4个列表项” 后,就会输出了 event 这个 object



在这里插入图片描述



?? 点击 “target” 继续展开后续的内容

在这里插入图片描述



?? 展开后,可见还有省略的内容,点击 “…” 这个省略的位置后,可以继续展示余下隐藏的内容。



在这里插入图片描述



?? 展开后,可见 textContent : “第4个列表项”



在这里插入图片描述



?? 添加判断条件为 点击 "第4个列表项"时,才会打印 “tesing for 事件代理”, 点击其它元素没有任何内容输出。



在这里插入图片描述



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <ul id="father">
        我是一个无序列表
        <li id="son">1个列表项</li>
        <li id="son">2个列表项</li>
        <li id="son">3个列表项</li>
        <li id="son">4个列表项</li>
        <li id="son">5个列表项</li>
    </ul>

    <script>
        // document.getElementById('father').onclick = function(){
        //     console.log('我点击了父元素');
        // }

        document.getElementById('father').addEventListener('click',function(event){
            if (event.target.textContent === "第4个列表项"){
            console.log('tesing for 事件代理');
            };
            // console.log(event);
        },true);

        // document.getElementById('son').onclick = function(){
        //     console.log('我点击了子元素');
        // }

    </script>
</body>

</html>


?? 怎么取消冒泡或者捕获 ? 通过 event.stopPropagation() 方法可以实现。



在这里插入图片描述



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <ul id="father">
        我是一个无序列表
        <li id="son">1个列表项</li>
        <!-- <li id="son">2个列表项</li>
        <li id="son">3个列表项</li>
        <li id="son">4个列表项</li>
        <li id="son">5个列表项</li> -->
    </ul>

    <script>
        // document.getElementById('father').onclick = function(){
        //     console.log('我点击了父元素');
        // }

        // document.getElementById('father').addEventListener('click',function(event){
        // //     if (event.target.textContent === "第4个列表项"){
        // //     console.log('tesing for 事件代理');
        // //     };
        // //     // console.log(event);
        // // },true);

        // document.getElementById('son').onclick = function(){
        //     console.log('我点击了子元素');
        // }

        document.getElementById('father').addEventListener('click',function(event){
            console.log('testing for click father element');
        });

        document.getElementById('son').addEventListener('click',function(event){
            console.log('testing for click son element');
            event.stopPropagation();
        });


    </script>
</body>

</html>


?? 再次点击 “第1个列表项” 后,只执行子元素输出 “testing for click son element”,不再执行父元素, 也就是不再输出 “testing for click father element”, 取消了冒泡。



在这里插入图片描述

文章来源:https://blog.csdn.net/weixin_48591974/article/details/135043453
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。