zoukankan      html  css  js  c++  java
  • 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>

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

  • 相关阅读:
    Python入门-函数进阶
    Python入门-初始函数
    Leetcode300. Longest Increasing Subsequence最长上升子序列
    Leetcode139. Word Break单词拆分
    Leetcode279. Perfect Squares完全平方数
    Leetcode319. Bulb Switcher灯泡开关
    Leetcode322. Coin Change零钱兑换
    二叉树三种遍历两种方法(递归和迭代)
    Leetcode145. Binary Tree Postorder Traversal二叉树的后序遍历
    Leetcode515. Find Largest Value in Each Tree Row在每个树行中找最大值
  • 原文地址:https://www.cnblogs.com/yishifuping/p/10304087.html
Copyright © 2011-2022 走看看