js事件(事件冒泡与事件捕获)

事件冒泡事件捕获分别由微软网景公司提出,这两个概念都是为了解决页面中事件流(事件发生顺序)的问题。

<div id='aa' click='po'>
        <p id='bb' click='on'>点击</p>
</div>

  上面两个点击事件如果点击的时候,到底谁会被先触发呢,为了解决这个问题微软和网景提出了两种几乎完全相反的概念。

事件冒泡

微软提出了名为事件冒泡(event bubbling)的事件流。事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象。

因此在事件冒泡的概念下在p元素上发生click事件的顺序应该是p -> div -> body -> html -> document

事件捕获

网景提出另一种事件流名为事件捕获(event capturing)。与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。

因此在事件捕获的概念下在p元素上发生click事件的顺序应该是document -> html -> body -> div -> p

后来 w3c 采用折中的方式,平息了战火,制定了统一的标准——先捕获再冒泡

冒泡的案例

<div id="s1">s1
    <div id="s2">s2</div>
</div>
<script>
    s1.addEventListener("click",function(e){
        console.log("s1 冒泡事件");
    },false);
    s2.addEventListener("click",function(e){
        console.log("s2 冒泡事件");
    },false);
</script>

  

捕获的案例

<div id="s1">s1
    <div id="s2">s2</div>
</div>
<script>
    s1.addEventListener("click",function(e){
        console.log("s1 捕获事件");
    },true);
    s2.addEventListener("click",function(e){
        console.log("s2 捕获事件");
    },true);
</script>

  当事件冒泡和捕获在一起出现的时候

<div id="s1">s1
    <div id="s2">s2</div>
</div>
<script>
s1.addEventListener("click",function(e){
        console.log("s1 冒泡事件");         
},false);
s2.addEventListener("click",function(e){
        console.log("s2 冒泡事件");
},false);
        
s1.addEventListener("click",function(e){
        console.log("s1 捕获事件");
},true);
        
s2.addEventListener("click",function(e){
        console.log("s2 捕获事件");
},true);
</script>

  

  • 对于非被点击dom节点则先执行捕获在执行冒泡

  • 对于被点击的dom节点则是先执行先注册的事件,无论冒泡还是捕获

事件冒泡和捕获,衍生出事件委托,因为当你点击子元素的时候,实际上走的是父组件的事件

<ul id="list">
    <li>111</li>
    <li>2222</li>
</ul>

  点击子元素的时候,由父元素去代为执行,能减少事件输出,代码的编写量

取消默认事件

w3c 的方法是 e.preventDefault(),IE 则是使用 e.returnValue = false;

取消默认事件,还可以用return来进行阻止

阻止冒泡的事件

w3c 的方法是 e.stopPropagation(),IE 则是使用 e.cancelBubble = true

IE9 之前的IE不支持 stopPropagation() 方法。相反,IE事件对象有一个 cancleBubble 属性,设置这个属性为 true 能阻止事件进一步传播。( IE8 及之前版本不支持事件传播的捕获阶段,所以冒泡是唯一待取消的事件传播。)

冒泡事件案例:

<div id='div' onclick='alert("div");'>
<ul onclick='alert("ul");'>
<li onclick='alert("li");'>test</li>
</ul>
</div>

  正常情况下,li>ul>div,这就是正常的冒泡的事件

阻止冒泡的事件:

window.event? window.event.cancelBubble = true : e.stopPropagation();

  阻止冒泡事件,案例

<html>
    <head>
        <style>
            #a{
                 300px;
                height: 300px;
                background: pink;
            }
            #b{
                 200px;
                height: 200px;
                background: blue;
            }
            #c{
                 100px;
                height: 100px;
                background: yellow;
            }
        </style>
    </head>
    <body>
        
        <div id="a">
            <div id="b">
                <div id="c"></div>
            </div>
        </div>
        <script>
            var a = document.getElementById("a"),
                b = document.getElementById("b"),
                c = document.getElementById("c");
            c.addEventListener("click", function (event) {
                console.log("c1");
                event.stopImmediatePropagation();
                // 注意第三个参数没有传进 false , 因为默认传进来的是 false
                //,代表冒泡阶段调用,个人认为处于目标阶段也会调用的
            });
            c.addEventListener("click", function (event) {
                console.log("c2");
            }, true);
            b.addEventListener("click", function (event) {
                console.log("b");
            }, true);
            a.addEventListener("click", function (event) {
                console.log("a1");
            }, true);
            a.addEventListener("click", function (event) {
                console.log("a2")
            });
            a.addEventListener("click", function (event) {
                console.log("a3");
                event.stopImmediatePropagation();
            }, true);
            a.addEventListener("click", function (event) {
                console.log("a4");
            }, true);
        </script>
    </body>
</html>

当时写博客的时候忘了写阻止冒泡的事件了,多谢老铁提醒!!!

原文地址:https://www.cnblogs.com/yishifuping/p/10304087.html