码迷,mamicode.com
首页 > Web开发 > 详细

JS:事件委托

时间:2018-12-08 17:10:07      阅读:453      评论:0      收藏:0      [点我收藏+]

标签:nodename   需求   分享   evel   eve   事件监听   events   use   而不是   

事件委托

  1. 事件流

    事件流描述的是从页面中接收事件的顺序。---JS高级程序设计(第3版)

    DOM Level 2 Events规定的事件流有三个阶段:①事件捕获阶段、②处于目标阶段、③事件冒泡阶段

    技术分享图片

  2. 事件委托

    当需要添加的事件过多时,可以使用事件委托,而事件委托实际上利用了事件冒泡的特性。

    使用事件委托还需了解事件对象(event):在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息。

    在此仅需知道在DOM标准中,event拥有一个target属性表示事件目标。

    event.target是一个触发事件的对象的引用。它与event.currentTarget不同, 当事件处理程序在事件的冒泡或捕获阶段被调用时。(mdn)

    具体Event详情可以查看MDN:Event


    如果你想要在大量子元素中单击任何一个都可以运行一段代码,您可以将事件监听器设置在其父节点上,并将事件监听器气泡的影响设置为每个子节点,而不是每个子节点单独设置事件监听器。(mdn)

    以下面的html代码为例:

    <ul id="list">
        <li id="one">do something</li>
        <li id="two">do something</li>
        <li id="three">do something</li>
    </ul>

    当需求是单击上面每个li标签都会执行各种操作时,使用事件委托是较好的选择。

    // bad (逐个 li 添加事件)
    let item1 = document.getElementById(‘one‘);
    let item2 = document.getElementById(‘two‘);
    let item3 = document.getElementById(‘three‘);
    
    item1.addEventListener(‘click‘, function(){...}, false);
    item1.addEventListener(‘click‘, function(){...}, false);
    item1.addEventListener(‘click‘, function(){...}, false);
    
    // event delegation (事件委托)
    let list = document.getElementById(‘list‘);
    list.addEventListener(‘click‘, function(e){
        if (e.target && e.target.nodeName == ‘LI‘) {
            switch (e.target.id) {
              case ‘one‘:
                do something;
                break;
    
              case ‘two‘:
                do something;
                break;
    
              case ‘three‘:
                do something;
                break;
            }
          }
    }, false);

    注意:当li标签被如pdiv等撑满时,点击的targetp标签而不是li标签会导致无法正确执行click事件。

    以下面的html代码为例:

    <ul id="list">
        <li id="one">do something</li>
        <li id="two">do something</li>
        <!-- 这里的 li 里面有个 p 标签 -->
        <li id="three"><p>do something</p></li>
      </ul>

    这样的情况可以使用递归 or 循环来处理,毕竟事件委托是利用事件冒泡的特性。

    //递归
    let list = document.getElementById(‘list‘);
    list.addEventListener(‘click‘, function(e){
     eventDelegation(e.target);
    }, false);
    
    function eventDelegation(target) {
     if (target && target.nodeName == ‘LI‘) {
            switch (target.id) {
              case ‘one‘:
                do something;
                return;
    
              case ‘two‘:
                do something;
                return;
    
              case ‘three‘:
                do something;
                return;
            }
        }
        return eventDelegation(target.parentNode);
    }
  3. 使用事件委托的优点

    a.减少DOM操作,使事件处理时间减少。
    b.减少内存空间的使用,提升性能。

    因为在JavaScript中,每个函数都是对象,对象越多,占用的内存也就越多,合理使用事件委托可以减少内存的占用。

  4. 注意事项

    比较适合使用事件委托的事件:clickmousedownmouseup等,而如mouseoutmouseover等则不太适合使用事件委托(虽然mouseout这些事件也冒泡,但通常需要确定元素的位置,所以不太推荐使用事件委托)。

    另外不会冒泡的事件是不适合使用事件委托的。

JS:事件委托

标签:nodename   需求   分享   evel   eve   事件监听   events   use   而不是   

原文地址:https://www.cnblogs.com/guolao/p/10088087.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!