zoukankan      html  css  js  c++  java
  • js的事件流你真的弄明白了吗?

    当浏览器发展到第四代时候,浏览器开发团队遇到了一个有意思的问题;页面的哪一部分会拥有某个特地的事件?要明白这个问题问的是什么,可以想象画在纸上的一组同心圆,如果你把手指放在圆心上,那么你的手指指向的不是一个圆,而是纸上所有的圆。两家公司的开发团队在这件事情上的看法是一致的,如果你单击了某个按钮,他们都认为单击事件不仅发生在按钮上,更是发生在了整个容器元素,甚至是整个页面。

    那么对于页面接收事件的顺序两者出现了不同的定义:捕获流 ( chrome )冒泡流( IE )。在事件监听addEventListener的第三个参数中,捕获流是 true,冒泡流是 false。主流浏览器默认的都是冒泡流机制,也就是第三个参数默认false。

    事件捕获:window -> document -> html -> body -> button  (原先的‘DOM2级事件’本来是规定事件应该从document对象出发的,但是后面几乎所有的浏览器还是拓展到了window对象层面)

    事件冒泡:button -> body -> html -> document -> window  

    事实上‘DOM2级事件’规定的事件流包括了三个阶段: 事件捕获阶段,处于目标阶段,事件冒泡阶段。(原先是规定捕获阶段不涉及事件目标的,但是后面高版本都会在捕获阶段触发事件对象上的事件)

    重点:处于目标阶段,即button的事件在捕获阶段和冒泡阶段都会被触发。

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title></title>
    <style>
    .box
    {
        position: relative;
        background-color: coral;
        border: 1px solid;
        padding: 50px;
    }
    .child {
        position: relative;
        background-color: pink;
         100px;
        height: 100px;
    }
    </style>
    </head>
    <body>
    <div id="A" class="box">
        <div id="B">
            <div id="C" class="child">点击该方块, 我是冒泡</div>
        </div>
    </div><br>
    <script>
    document.getElementById("A").addEventListener("click", function(e)
    {
        console.log("1 捕获");
    }, true);
    document.getElementById("B").addEventListener("click", function(e)
    {
        console.log("2 捕获");
        // e.stopPropagation()
    }, true);
    document.getElementById("C").addEventListener("click", function(e)
    {
        console.log("捕获阶段触发目标");
        // e.stopPropagation()
    }, true);
    document.getElementById("C").addEventListener("click", function()
    {
        console.log("冒泡触发目标");
    }, false);
    document.getElementById("B").addEventListener("click", function()
    {
        console.log("1 冒泡");
    }, false);
    document.getElementById("A").addEventListener("click", function()
    {
        console.log("2 冒泡");
    }, false);
    
    </script>
    
    </body>
    </html>
    

      

     

    执行结果如下:

     

    值得注意的是,捕获阶段或者冒泡阶段对应的在 C 上的事件其实并不是 先捕获阶段触发目标 然后是冒泡阶段触发目标,在C上的事件其实是都是触发的,触发顺序取决于你写的顺序。不信,换下顺序如下

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title></title>
    <style>
    .box
    {
        position: relative;
        background-color: coral;
        border: 1px solid;
        padding: 50px;
    }
    .child {
        position: relative;
        background-color: pink;
         100px;
        height: 100px;
    }
    </style>
    </head>
    <body>
    <div id="A" class="box">
        <div id="B">
            <div id="C" class="child">点击该方块, 我是冒泡</div>
        </div>
    </div><br>
    <script>
    document.getElementById("A").addEventListener("click", function(e)
    {
        console.log("1 捕获");
    }, true);
    document.getElementById("B").addEventListener("click", function(e)
    {
        console.log("2 捕获");
        // e.stopPropagation()
    }, true);
    document.getElementById("C").addEventListener("click", function()
    {
        console.log("冒泡触发目标");
    }, false);
    document.getElementById("C").addEventListener("click", function(e)
    {
        console.log("捕获阶段触发目标");
        // e.stopPropagation()
    }, true);
    
    document.getElementById("B").addEventListener("click", function()
    {
        console.log("1 冒泡");
    }, false);
    document.getElementById("A").addEventListener("click", function()
    {
        console.log("2 冒泡");
    }, false);
    
    </script>
    
    </body>
    </html>
    

     执行结果如下:

     

    接下来继续说一下阻止冒泡,假设我在  console.log("1 捕获") 或者 console.log("2 捕获") 后面加上  e.stopPropagation(),后面的事件还能触发吗?单单是只把冒泡流扼杀了吗?

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title></title>
    <style>
    .box
    {
        position: relative;
        background-color: coral;
        border: 1px solid;
        padding: 50px;
    }
    .child {
        position: relative;
        background-color: pink;
         100px;
        height: 100px;
    }
    </style>
    </head>
    <body>
    <div id="A" class="box">
        <div id="B">
            <div id="C" class="child">点击该方块, 我是冒泡</div>
        </div>
    </div><br>
    <script>
    document.getElementById("A").addEventListener("click", function(e)
    {
        console.log("1 捕获");
        e.stopPropagation()
    }, true);
    document.getElementById("B").addEventListener("click", function(e)
    {
        console.log("2 捕获");
        
    }, true);
    document.getElementById("C").addEventListener("click", function()
    {
        console.log("冒泡触发目标");
    }, false);
    document.getElementById("C").addEventListener("click", function(e)
    {
        console.log("捕获阶段触发目标");
        // e.stopPropagation()
    }, true);
    
    document.getElementById("B").addEventListener("click", function()
    {
        console.log("1 冒泡");
    }, false);
    document.getElementById("A").addEventListener("click", function()
    {
        console.log("2 冒泡");
    }, false);
    
    </script>
    
    </body>
    </html>
    

      

    事实上,它是把后面的事件流都打断了。而如果 e.stopPropagation() 是写在  console.log("捕获阶段触发目标") 或者  console.log("冒泡触发目标")后面,目标阶段都点击事件都会执行,执行按你写的顺序来。

    Propagation英文意思是‘传播’ stopPropagation 就是阻止事件传播,阻止事件流的继续往下发生。

    所以stopPropagation()方法事实上是打断了事件流继续执行,而我们一般时候是直接写在目标事件的点击函数里,就起到了阻止冒泡的作用!

      

  • 相关阅读:
    LeetCode449. 序列化和反序列化二叉搜索树
    LeetCode448. 找到所有数组中消失的数字
    一行代码如何隐藏 Linux 进程?
    C语言这么厉害,它自身又是用什么语言写的?
    了解C语言,是否代表了解C ++的一半?
    C语言小白那些不知道的事儿
    6 条 Git 实用技巧
    干货来袭,收藏方便找到该网站
    零基础小白如何入门Shell,快来看看(收藏)这篇大总结!!
    Java用于嵌入式系统的优点和局限
  • 原文地址:https://www.cnblogs.com/hjj2ldq/p/9892409.html
Copyright © 2011-2022 走看看