js中的事件传播过程

引子:
父div添加监听事件,子div设置监听事件,点击子元素,会出现什么结果

事件传播的三个过程,事件捕获阶段、处于目标阶段、事件冒泡阶段。
事件捕获由远及近逐渐靠近事件目标,事件冒泡由事件目标逐渐向上冒泡
那是不是所有的事件都要经历这三个过程呢?其实不然

IE:它认为事件流应该是事件冒泡。
Netscape:它则认为事件流应该是事件捕获。
W3C:首先是事件捕获然后事件冒泡

在支持w3c的浏览器中,程序员可以通过设置addEventListener(type,handler,useCapture)中的userCapture值来决定元素是在冒泡阶段执行事件还是捕获阶段执行,默认为false,即冒泡阶段。
IE没有提供选择,事件只能在冒泡阶段捕获。
偷个图[https://www.w3cin.com/2016/06/03/%E6%B5%8F%E8%A7%88%E5%99%A8%E7%9A%84DOM%E4%BA%8B%E4%BB%B6/]

事件传播三个阶段

IE9、Opera、Firefox、Chrome和Safari都支持DOM事件流。
写个代码测试一下
页面内容很简单,父div子div

<div id="parent">
        parent
        <div id="child">child</div>
    </div>

因为考虑到浏览器兼容性,先写一个跨浏览器事件处理函数

var eventHandler={
            addEventHandler:function(ele,type,handler,capture){
                if(ele.addEventListener){
                    ele.addEventListener(type,handler,capture);
                }else if(ele.attachEvent){
                    //ie下是需要加on的
                    //ele.attachEvent(type,handler);
                    ele.attachEvent('on'+type,handler);
                }else{
                    ele['on'+type]=handler;
                }
            },
            stopPropagation:function(event){
                event=event||window.event;
                if(event.stopPropagation){
                    event.stopPropagation();
                }else{
                    event.cancelBubble=true;
                }
            },
            preventDefault:function(event){
                event=event||window.event;
                if(event.preventDefault){
                    event.preventDefault();
                }else{
                    event.returnValue=true;
                }
            }
        }

进入正题,对父子div添加监听函数

window.onload=function(){
            var parent=document.getElementById("parent");
            var child=document.getElementById("child");
            eventHandler.addEventHandler(parent,'click',function(e){
                console.log("parent捕获阶段");
            },true);
            eventHandler.addEventHandler(parent,'click',function(e){
                console.log("parent冒泡阶段");
            },false);
            eventHandler.addEventHandler(child,'click',function(e){
                console.log("child冒泡阶段");
            },false);
            eventHandler.addEventHandler(child,'click',function(e){
                console.log("child捕获阶段");
            },true);
        }

chrome下测试结果:

image.png

事件果然是从父div到子div被捕获,然后从子div到父div冒泡。
注意:此处对子div绑定了两个事件,即冒泡事件和捕获事件,这两个事件的执行顺序是按照绑定的先后顺序执行的,如果把两个执行函数替换一下,结果就会先打印child捕获阶段,再打印child冒泡阶段,不信你试试~

ie8下的测试结果:

image.png

ie下不存在捕获阶段,直接从冒泡阶段开始,由子div到父div打印事件。此处应该注意,对重复绑定的事件,在IE9以下的浏览器中执行顺序都是反着的,因为IE9开始已经支持addEventListener()方法所以不会在有这个问题了。
比如现在我把事件的执行顺序改为

eventHandler.addEventHandler(parent,'click',function(e){
                console.log("parent捕获阶段");
                // eventHandler.stopPropagation(e);
            },true);
            eventHandler.addEventHandler(parent,'click',function(e){
                console.log("parent冒泡阶段");
            },false);
            eventHandler.addEventHandler(child,'click',function(e){
                console.log("child捕获阶段");
            },true);
            eventHandler.addEventHandler(child,'click',function(e){
                console.log("child冒泡阶段");
            },false);

chrome下的执行结果为:

image.png

ie8下的执行结果为:

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 以下文章为转载,对理解JavaScript中的事件处理机制很有帮助,浅显易懂,特分享于此。 什么是事件? 事件(E...
    jxyjxy阅读 3,081评论 1 10
  • 1. 事件冒泡与事件捕获 事件冒泡和事件捕获分别由微软和网景公司提出,这两个概念都是为了解决页面中事件流(事件发生...
    cbw100阅读 2,758评论 0 8
  • 声明:本文来源于http://www.webzsky.com/?p=731我只是在这里作为自己的学习笔记整理一下(...
    angryyan阅读 7,156评论 1 6
  • 1.何谓事件 用户和网页交互时的行为,动作,称之为事件; 2.监视事件 现实生活中,为了监视车辆是否违章,通过在红...
    草鞋弟阅读 651评论 0 0
  • 磨山的来历 张淑英 在永城市芒山镇芒砀山群的众多山中,有一座山叫磨山。这座山因何得名?关于它的名字其实是有着一段动...
    秦小简阅读 203评论 0 0