• js事件的捕获和冒泡阶段


    讨论的主要是两个事件模型:IE事件模型与DOM事件模型

    IE内核浏览器的事件模型是冒泡型事件(没有捕获事件过程),事件句柄的触发顺序是从ChildNode到ParentNode。 

     <div id="ancestor"> 
    
           <button id="child"> 
    
               Open the console and click me 
    
           </button> 
    
    </div> 

    以上的HTML代码在IE内核下,事件是这样传播的:{

    1、Button#child; 
    2、div#ancestor; 
    3、Body; 
    4、Document 

    DOM标准的浏览器事件是:捕获事件和冒泡事件。

    捕获事件过程:{

    1、Window 
    2、Document 
    3、Body 
    4、Div#ancestor 
    5、Button#child 

    }

    冒泡事件过程:{

    6、Div#ancestor 
    7、Body 
    8、Document 
    9、Window 

    }

    当开发者在一个元素上注册了事件后,这个事件的响应顺序是从window(最顶层)开始一级一级的向下传播,然后到了该元素后事件捕获过程结束,事件开如冒泡,一级一级向父层元素冒泡(请注意第6步)。

    当然,开发者可以很轻松的决定DOM标准的浏览器中的事件需要在哪个传播过程触发。

    事件的注册机制:

    DOM标准的浏览器事件注册方法是通过addEventListener方法注册,而IE内核的浏览器则是通过attachEvent方法注册。 
    这两个方法的区别:
    addEventListener方法带有三个参数,分别是:eventType、handler、useCapture。 
    eventType不带有on字符串; 
    handler参数是一个事件句柄,这个函数或方法带有一个事件对象参数; 
    useCapture参数决定了事件句柄触发在哪种事件传播阶段,如果useCapture为true则为捕获阶段,反之则为冒泡阶段。 

    继续看演示: 

    var ancestorHandler = function (e){ 
    
    //...... 
    
     }, 
    
     childHandler = function (e){ 
    
    //...... 
    
    }; 
    
     document.querySelector('#ancestor').addEventListener('click',ancestorHandler,false);//注意第三个参数 ,注册了一个在冒泡阶段触发的事件句柄
    
     document.querySelector('#child').addEventListener('click',childHandler,true);//注意第三个参数 ,注册了一个在捕获阶段的事件句柄

     
    当用户在这个DIV元素上点击时,事件的执行顺序是childHandler、ancestorHandler。 

    原因:按钮的事件是在捕获阶段触发的,也就是从上到下,而DIV的事件是注册在冒泡阶段,也就是点击了这个按钮开始从这个按钮的位置往上冒泡。

    阻止事件的冒泡:

    DOM事件对象提供了stopPropagation方法用于阻止事件流。 

    var ancestorHandler = function (e){ 
      //...... 
    }, 
    childHandler = function (e){ 
      e.stopPropagation(); 
      //...... 
    }; 


    以上代码在childHandler函数中添加了e.stopPropagation()代码片段,它将阻止事件流,事件流包括捕获阶段及冒泡阶段的事件流。 

    再修改上面的代码如下: 

    var ancestorHandler = function (e){ 
      //...... 
    }, 
    childHandler = function (e){ 
      //...... 
    }; 
    document.querySelector('#ancestor').addEventListener('click',ancestorHandler,true);//注意第三个参数 
    document.querySelector('#child').addEventListener('click',childHandler,true);//注意第三个参数 


    以上的代码产生的结果是:用户在DIV元素上单击时,将会依次触发ancestorHandler、childHandler函数,为什么?因为我们将div#ancestor的事件注册到捕获阶段了,也就是从上至下。当然了我们还可以阻止childHandler方法的执行。

    以上代码将阻止按钮的事件触发。当用户点击了DIV的区域,仅仅触发ancestorHandler函数,因为阻止了事件流。 

    IE内核的浏览器中是如何注册事件的。IE内核提供了attachEvent方法为元素注册事件,注意该方法与DOM的addEventListener方法区别很大!该方法带有两个参数:

    {

    eventType 事件类型,请注意这个参数与addEventListener的eventType的区别,它必须带有on; 

    handler 事件句柄 ,请注意attachEvent没有提供事件捕获阶段的参数,IE内核的事件都是发生在冒泡阶段! 

    }

    var ancestorHandler = function (e){ 
      //...... 
    }, 
    childHandler = function (e){ 
      //...... 
    }; 
    document.getElementById('ancestor').attachEvent('onclick',ancestorHandler);//注意没有第三个参数 
    document.getElementById('child').attachEvent('onclick',childHandler);//注意没有第三个参数 


    以上代码在IE中将为DIV元素和按钮元素注册了不同的事件。 

    另外还有一些注意事项: 

    1、DOM标准的addEventListener方法执行事件的顺序是按照事件注册的顺序执行的。而attachEvent方法则相反–后注册的事件先觖发,先注册的事件后触发。 
    2、DOM标准的浏览器文本节点也会冒泡,而IE内核的浏览器文本节点不会冒泡。 
    3、DOM标准的浏览器事件对象与IE内核的浏览器事件不同(具体请参阅http://www.quirksmode.org/js/introevents.html)。 
    4、DOM标准的浏览器事件卸载方式与IE内核的事件卸载方式不同。 
    1 object.removeEventListener(eventType,handler,useCapture);//DOM标准的事件卸载方式 
    2 object.detachEvent(eventType,handler);//IE内核的事件卸载方式 

    在DOM标准的事件卸载方式中需要注意的是:事件捕获的参数。如果你的事件是注册在捕获阶段,则卸载事件时,必须将其指定为捕获阶段(true),否则无法卸载;如果你的事件注册在注册在冒泡阶段,则必须将其指定为冒泡阶段(false),否则同样无法卸载!

                              写作不易,难免有疏漏和错误,还请慷慨指正,不错请推荐


                                          每天多学一点点     代码少敲一点点 

  • 相关阅读:
    Tomcat通过脚本自动部署
    【转】调用百度API,HTML在线文字转语音播报
    vim 多行注释消除注释,多行删除
    sublime快捷键
    引号-下划线,连接多个变量
    图片压缩工具optipng/jpegoptim安装
    netsh-winsock-reset;ping的通公网IP和DNS地址和内网网关,就是不能解析域名;
    mysql简单性能排查
    nginx-upstream-keepalive;accept_mutex-proxy_http_version-1.1-proxy_set_header-connection
    icmp,tcp,traceroute,ping,iptables
  • 原文地址:https://www.cnblogs.com/liuyitian/p/4460194.html
Copyright © 2020-2023  润新知