zoukankan      html  css  js  c++  java
  • 事件的捕获-冒泡机制及事件委托

    Javascript事件模型系列(二)事件的捕获-冒泡机制及事件委托

    一、事件的捕获与冒泡

       由W3C规定的DOM2标准中,一次事件的完整过程包括三步:捕获→执行目标元素的监听函数→冒泡,在捕获和冒泡阶段,会依次检查途径的每个节点,如果该节点注册了相应的监听函数,则执行监听函数。以下面的HTML结构为例:

    复制代码
    <div id="parentdiv">
           父亲
           <div id="childdiv">孩子</div>
    </div>
    复制代码

      执行的流程应该是这样的:

      下面是一组例子,分别点击孩子节点可以清楚的看到第三个参数的影响:

    父亲
    孩子
     
    父亲节点的监听函数在捕获阶段执行:
    var parent1 = document.getElementById('parentdiv1');
    var child1 = document.getElementById('childdiv1');
    parent.addEventListener('click',function(){alert('父亲被点击了');},true);//第三个参数为true
    child.addEventListener('click',function(){alert('孩子被点击了');},false);
     
    父亲
    孩子
     
    父亲节点的监听函数在冒泡阶段执行:
    var parent2 = document.getElementById('parentdiv2');
    var child2 = document.getElementById('childdiv2');
    parent.addEventListener('click',function(){alert('父亲被点击了');},false);//第三个参数为false
    child.addEventListener('click',function(){alert('孩子被点击了');},false);
     
    父亲
    孩子
     
    父亲节点的监听函数在捕获冒泡阶段都执行:
    var parent3 = document.getElementById('parentdiv3');
    var child3 = document.getElementById('childdiv3');
    parent.addEventListener('click',function(){alert('父亲被点击了');},true);//第三个参数为true
    parent.addEventListener('click',function(){alert('父亲被点击了');},false);//第三个参数为false
    child.addEventListener('click',function(){alert('孩子被点击了');},false);

      如果不想让事件向上冒泡,可以在监听函数中调用event.stopPrapagation()来完成,这样父亲节点就捕捉不到该事件了。在实际的开发中,这一用处还是挺多的。

    二、事件委托机制

           知道了事件的捕获冒泡机制,我们可以利用它来实现更方便的程序控制,事件委托便是最典型的应用之一。下面来说说javascript中的事件委托机制。什么叫委托呢?想想我们现实生活中,自己不想干的事,让别人来帮忙完成,这就是把事情“委托”给别人。Javascript的事件委托机制也是这个道理,本来一个监听函数要处理节点a触发的事件,现在把这个监听函数绑定到节点a的父层节点上,让它的父辈来完成事件的监听,这样就把事情“委托”了过去。在父辈元素的监听函数中,可通过event.target属性拿到触发事件的原始元素,然后再对其进行相关处理。

           那这样做有什么好处呢?最大的用处便是监听动态增加的元素。比如我们现在有这样的需求,点击下面每个列表项弹出各自的内容,现在随着web应用的盛行,网页中使用异步请求来动态加载节点已经变的很普遍,所以我们点击下方的按钮要在列表中增加一项,并且点击新增加的节点也要弹出内容。HTML结构如下:

    复制代码
    <ol id="olist">
        <li>列表内容1</li>
        <li>列表内容2</li>
        <li>列表内容3</li>
        <li>列表内容4</li>
        <li>列表内容5</li>
    </ol>
    复制代码

      若我们使用之前的监听器绑定方式,需要遍历所有的li元素并监听,代码应该是这样的:

    复制代码
    var listArray = document.getElementById('olist').childNodes;
    for(var i=0;i<listArray.length;i++){
        listArray[i].addEventListener('click',function({
                alert(this.innerText);
            });
    }
    复制代码

      运行效果如下:

    1. 列表内容1
    2. 列表内容2
    3. 列表内容3
    4. 列表内容4
    5. 列表内容5

      可以发现当新增元素后,点击它并没有弹出内容。那是当然的了,因为我们并没有给新增的元素绑定监听器,为了实现点击新增元素也弹出内容,我们不得不在每次新增一个元素后,再进行一次绑定。加一个绑一个,加一个绑一个,累不累啊!你不累浏览器都累了!这样做导致的性能开销是可想而知的,而且浏览器还要维系n多元素与应的监听函数的映射关系,会占用大量内存。

           面对这样拖沓冗杂的代码,你是不是已经不能忍,想要高喊一声:大地!快使用光能力量!好,接下来该秘密武器登场了,看看使用事件委托的效果,代码如下:

    复制代码
    var olist = document.getElementById('olist');
    olist.addEventListener('click',function(){
        alert(event.target.innerText);
    },false);
    复制代码

      看看实际运行的效果:

    1. 列表内容1
    2. 列表内容2
    3. 列表内容3
    4. 列表内容4
    5. 列表内容5

      我们并未给li元素绑定任何监听器,而是监听它的父元素ul,等到事件冒泡上来的时候,在处理函数中通过event.target获得触发事件的li元素,进行相关处理。这样做的好处是显而易见的,首先只进行了一次监听器的绑定,浏览器轻松,其次动态增加元素后你也不必要再绑定监听器,你也轻松。正所谓大家好才是真的好!

           本篇的基本内容就介绍完了,你是不是感觉有点奇妙,我平时写程序的时候没关心这些也仍然能完成工作呀?那我就得问你是不是使用js框架,使用jQuery了,事实上,jQuery提供的on、live等方法就已经对事件委托进行了封装,为委托机制的推广悄悄做了底层贡献,你没感觉到而已。jQuery中的各种事件监听方式也需要我们有一个清楚的了解,才能正确的使用,高效的完成工作。这些内容将放在下一篇介绍。

     
     
     
    标签: javascript
  • 相关阅读:
    1144 The Missing Number (20分)
    1145 Hashing
    1146 Topological Order (25分)
    1147 Heaps (30分)
    1148 Werewolf
    1149 Dangerous Goods Packaging (25分)
    TypeReference
    Supervisor安装与配置()二
    谷粒商城ES调用(十九)
    Found interface org.elasticsearch.common.bytes.BytesReference, but class was expected
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3267317.html
Copyright © 2011-2022 走看看