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

    写在前面

    DOM 文档编程接口中并没有为 DOM元素 提供原生的事件委托接口。对于 DOM 中的事件机制,原生 DOM 仅仅提供了事件模型的接口:事件监听与处理。事件监听与处理目前是有两种方式实现,即 on{eventtype}addEventListener。具体参看上篇博客 最全的DOM事件笔记

    事件委托思想是程序员在实际需求中发掘出来的。

    在 原生DOM 提供的 DOM事件对象 的基础上,有好几种实现事件委托的方法。比如 JQuery 库中封装好的 on() 方法。那么下面介绍几种在原生 DOM语法 中的事件委托的实现方法。

    假设场景如下:

    <div class="grandpa">
          <div class="father">
                <div class="child">
                  <span class="text">文字</span>
                </div>
          </div>
    </div>
    

    需求如下:

    对儿子元素(.child)进行 click 事件监听,当该元素被点击时,在控制台输出 我是儿子,我被点击了!

    1. 常见但错误的方法

    const grandpaEl = document.getElementsByClassName('grandpa')[0];
    grandpaEl.addEventListener('click', (e)=>{
          const el = e.target;
          if(el.className === 'child'){
                console.log('我是儿子,我被点击了!');
          }
    })
    

    这样得到的结果是,当点击 .child 元素时会正确输出,但当点击 .child 里面的 .text 元素时不会正确输出。

    根据我们的实际需求,当点击父元素包裹的子元素时,也是相当于点击了父元素,应当触发对应的事件处理函数。因此此种方法严格来说是错误的。

    此种方法只适用于被监听的元素没有后代元素时使用。

    2. 递归方法

    const grandpaEl = document.getElementsByClassName('grandpa')[0];
    grandpaEl.addEventListener('click', (e)=>{
          let el = e.target;
          while(!el.matches('.child')){
                if(el === grandpaEl){
                      el = null;
                      break;
                }
                el = el.parentNode;
          }
          if(el){
                console.log('我是儿子,我被点击了!');
          }
    })
    

    可以封装成一个事件委托(代理)函数如下:

    function delegate(agent, eventType, clientSelector, fn){
          agent.addEventListener(eventType, (e)=>{
                let el = e.target;
                while(!el.matches(clientSelector)){
                      if(el === agent){
                            el === null;
                            break;
                      }
                      el = el.parentNode;     
                }
                el && fn.call(el, e, el);
          })
          return agent;
    }
    

    3. 巧用事件对象的 path 属性

    const grandpaEl = document.getElementsByClassName('grandpa')[0];
    grandpaEl.addEventListener('click', (e)=>{
         let child = e.path.find(el => el.matches('.child'));
         if(child){
               console.log('我是儿子,我被点击了!');
         }
    })
    
  • 相关阅读:
    Python小工具:统计代码行数
    计算机图形学复习(一)
    牛客多校训练第一场 J.Different Integers
    数据校验码概述
    数据库复习第二章
    数据库复习第一章
    自动化AC器(带界面版)
    ZOJ 3747 Attack on Titans
    Codeforces Round #245 (Div. 1) B. Working out
    HDU 6266 Hakase and Nano 【博弈论】
  • 原文地址:https://www.cnblogs.com/lovevin/p/13411994.html
Copyright © 2011-2022 走看看