zoukankan      html  css  js  c++  java
  • javascript冒泡事件详解

    • 冒泡事件

      定义:当多个Dom元素互相嵌套的时候,一个元素触发了某个事件(例如Click事件),那么嵌套此事件的所有元素都会被触发一次Click事件,注意:只会触发他的直系亲属元素,而与其自己,父级,爷级等等同级的亲戚集是不会触发的

    • 捕获事件:

      *定义:** 同冒泡事件含义相似,只是将冒泡事件的触发顺序倒过来即可

    • DOM事件流

      元素的触发流程分为三个阶段

      1. 捕获阶段:先从祖先级一直找到触发的源元素(所有元素都触发了相同事件)

      2. 目标阶段:找到原元素,然后触发源元素的事件

      3. 冒泡阶段:然后重新流回祖先元素,又触发了一遍相同事件

    • 思考: 按照上面的事件流,岂不是一个元素会触发两次事件?那这不是很奇怪吗:其实在我们一般开发过程中都是用Jqueryon 方法来绑定的(推荐使用),绑定后,只会触发冒泡事件。那么什么时候会涉及到这个捕获阶段呢,在原生的javascript中,就会有此方法的使用,且看下面详解

    • 详解 addEventListener/removeEventListener

      作用: 原生的事件绑定方法


      // type:事件类型,不含"on",比如"click"、"mouseover"、"keydown";
      // 而attachEvent的事件名称,含含"on",比如"onclick"、"onmouseover"、"onkeydown";
      // listener:事件处理函数
      // useCapture是事件冒泡,还是事件捕获(true),默认false,代表事件冒泡类型
      addEventListener(type, listener, useCapture);

      特点:

      1. 一个元素可以同时绑定两种类型(捕获/冒泡)

      2. 一个同种类型的元素重复绑定同一个事件函数,只绑定一次

      3. 一个元素可以重复绑定多个不同的函数,且是叠加而非覆盖

    • 触发流程:

      1. 首先源目标触发了事件

      2. 开始捕获阶段,将其直系亲属(类型为捕获)的事件触发

      3. 到达源元素,触发事件方法,如果重复绑定多个,则按绑定顺序触发(源元素的类型其实没有影响)

      4. 然后开始冒泡排序,将其直系亲属(类型为冒泡)的事件触发

      <script>

      window.onload = function(){
      var outA = document.getElementById("outA");  
      var outB = document.getElementById("outB");  
      var outC = document.getElementById("outC");  

      // 目标(自身触发事件,是冒泡还是捕获无所谓)
      outC.addEventListener('click',function(){alert("target2");},true);
      outC.addEventListener('click',function(){alert("target1");},true);

      // 事件冒泡
      outA.addEventListener('click',function(){alert("bubble1");},false);
      outB.addEventListener('click',function(){alert("bubble2");},false);

      // 事件捕获
      outA.addEventListener('click',function(){alert("capture1");},true);
      outB.addEventListener('click',function(){alert("capture2");},true);
      };

      </script>

      <body>
      <div id="outA" style="400px; height:400px; background:#CDC9C9;position:relative;">
      <div id="outB" style="height:200; background:#0000ff;top:100px;position:relative;">
      <div id="outC" style="height:100px; background:#FFB90F;top:50px;position:relative;"></div>
      </div>
      </div>
      </body>

      点击outC的时候,打印顺序是:capture1-->capture2-->target2-->target1-->bubble2-->bubble1

      结论:捕获阶段的处理函数最先执行,其次是目标阶段的处理函数,最后是冒泡阶段的处理函数。目标阶段的处理函数,先注册的先执行,后注册的后执行

    • 如何解决冒泡/捕获事件的影响

      目的: 我们很清楚,解决冒泡和捕获事件的影响,只需要在源元素触发完事件之后停止事件的传播即可

      方式:

      1. event.stopPropagation(); 只阻止了冒泡事件, 默认行为没有阻止(超链接a嵌套按钮,依然会跳转)

      2. event.preventDefault(); 只阻止了默认事件,冒泡事件没有阻止(超链接a嵌套按钮,不跳转,但会触发点击事件)

      3. return false; 冒泡事件和默认事件都阻止

      <script>

      window.onload = function(){
      var outA = document.getElementById("outA");  
      var outB = document.getElementById("outB");  
      var outC = document.getElementById("outC");  

      // 目标
      outC.addEventListener('click',function(event){
      alert("target");
      event.stopPropagation();
      },false);

      // 事件冒泡
      outA.addEventListener('click',function(){alert("bubble");},false);

      // 事件捕获
      outA.addEventListener('click',function(){alert("capture");},true);

      };

      </script>

      <body>
      <div id="outA" style="400px; height:400px; background:#CDC9C9;position:relative;">
      <div id="outB" style="height:200; background:#0000ff;top:100px;position:relative;">
      <div id="outC" style="height:100px; background:#FFB90F;top:50px;position:relative;"></div>
      </div>
      </div>
      </body>
      capture-->target,不会打印出bubble。因为当事件传播到outC上的处理函数时,通过stopPropagation阻止了事件的继续传播,所以不会继续传播到冒泡阶段,当然如果此方法放到了捕获中,那么就只会打印出capture了
    • 注意点:

      今天用 on 绑定的时候,div 嵌套按钮,按钮里的事件触发带有ajax的请求,结果点击确实进入了按钮事件方法中,但是还没有进入回调函数,就跳转到div的点击事件方法中了,然后再跳回回调方法中,采用了以下方法解决


      <html>
      <head>
         <meta name="viewport" content="width=device-width" />
         <title>webApi测试</title>
         <script src="~/js/jquery.min.js"></script>
      </head>
      <body>
         <div id="first">
         </div>
         <div id="outA" style="400px; height:400px; background:#CDC9C9;position:relative;">
             <div id="outB" style="height:200; background:#0000ff;top:100px;position:relative;">
                 <div id="outC" style="height:100px; background:#FFB90F;top:50px;position:relative;"></div>
             </div>
             </div>
         </div>
      </body>
      </html>

      <script>
         $(function () {

             $("#outC").on ("click",function () { alert("C")});
             $("#outB").on ("click",function () { alert("B") });
             $("#outA").on("click", function () { alert("A") });
             $("#outD").on("click", function () { alert("D") });

             $("#first").on("click", function () { debugger; alert("最外层div") });
             $("#routeTest").on("click", ajaxFunction);

             function ajaxFunction() {
                 debugger;
                 //event.cancelBubble = true;//取消事件的冒泡,效果同下
                 //return false//此方法会导致此方法直接结束,因此不能直接使用
                 event.stopPropagation();  
                 $.ajax({
                     url: "/Course/GetCourseByRoute?temp"+Date.parse(new Date()),
                     type: 'get',
                     success: function (res) {
                         debugger;
                         alert(res);
                    }
                });
            }
        });
      </script>

       

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    网络字节序与主机字节序
    Maven2插件开发详解
    NetBeans 时事通讯(刊号 # 30 Oct 15, 2008)
    NetBeans 时事通讯(刊号 # 30 Oct 15, 2008)
    Grsync:rsync 的图形化界面
    Windows Socket网络编程学习笔记一
    如何调试MFC中的内存泄漏
    内存池(MemPool)技术详解
    These codes are How to use Lucence.net
    VC控制台程序的文字颜色
  • 原文地址:https://www.cnblogs.com/wang-min/p/10853423.html
Copyright © 2011-2022 走看看