zoukankan      html  css  js  c++  java
  • JS:事件委托

    事件委托

    1. 事件流

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

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

      capture_and_bubbling

    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这些事件也冒泡,但通常需要确定元素的位置,所以不太推荐使用事件委托)。

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

  • 相关阅读:
    大型高并发高负载网站的系统架构(转)
    亿级数据的高并发通用搜索引擎架构设计(转-张宴)
    VMware12版虚拟机怎么安装win7系统(详细教程
    Linux-CentOS7 安装VMware Workstation 12
    IntelliJ IDEA 12创建Maven管理的Java Web项目(图解)
    idea 创建maven工程(入门)
    SQL中inner join、outer join和cross join的区别
    OLTP和OLAP有何区别?
    HAWQ 官方文档创建filespace,tablespace,database,table
    DQL、DML、DDL、DCL的概念与区别
  • 原文地址:https://www.cnblogs.com/guolao/p/10088087.html
Copyright © 2011-2022 走看看