简介

由于事件在冒泡阶段向上传播到父节点,因此可以把子节点监听的事件在父节点的监听,由父节点的监听函数统一处理多个子元素的的事件,这种方法就叫做事件的代理,处理如下:

var ul = document.querySelector('ul');ul.addEventListener('click', function (event) {if (event.target.tagName.toLowerCase() === 'li') {// some code}
});

这样做的好处:

只需在父节点定义一个监听函数,就可以统一处理子节点的事件了;
动态添加子节点,也可以监听到;

下面呢?我们就手动实现下事件代理

实现步骤

创建一个Delegator类,定义一个on方法(监听),再定义一个destroy方式(用于注销事件)

!function (root, doc) {class Delegator {/**@param 顶级选择器(代理者)*/constructor (selector) {}/**绑定事件*@param event 绑定事件类型*@param selector 需要被代理的选择器*@param fn 触发函数* */on (event, selector, fn) {}/**移除事件*/destroy () {}}root.Delegator = Delegator
}(window, document)

定义两个实例属性,分别用来接受root节点和被代理的元素对象。

 constructor (selector) {this.root = document.querySelector(selector);//顶级domthis.delegatorEvents = {//代理元素及事件//evenType:[{//matcher:selector,//元素dom节点//callback:fn,//事件函数}]};}

绑定事件具体逻辑

1.事件代理触发顺序满足冒泡规则;;
2.this 应当指向正确的元素;
3.相同事件只做一个监听
4.新添加元素也能够响应绑定;

   constructor (selector) {this.root = document.querySelector(selector);//顶级domthis.delegatorEvents = {};//代理元素及事件//代理逻辑this.delegator = e => {        let currentNode = e.target;//目标节点const targetEventList = this.delegatorEvents[e.type];//实现冒泡规则while (currentNode !== e.currentTarget) {targetEventList.forEach(target => {if (currentNode.matches(target.matcher)) {//开始委托并把当前目标节点的event对象传过去,改为this指向target.callback.call(currentNode, e);}})currentNode = currentNode.parentNode;}}}/**绑定事件*@param event 绑定事件类型*@param selector 需要被代理的选择器*@param fn 触发函数* */on (event, selector, fn) {//相同事件只添加一次,如果存在,则再对应的代理事件里添加if (!this.delegatorEvents[event]) {this.delegatorEvents[event] = [{matcher: selector,callback: fn}]this.root.addEventListener(event, this.delegator);}else{this.delegatorEvents[event].push({matcher: selector,callback: fn})}return this;}

注销事件

    /**移除事件*/destroy () {Object.keys(this.delegatorEvents).forEach(eventName => {this.root.removeEventListener(eventName, this.delegator)});}

全部代码

!function (root, doc) {class Delegator {/**@param 顶级选择器(代理者)*/constructor (selector) {this.root = document.querySelector(selector);//顶级domthis.delegatorEvents = {};//代理元素及事件//代理逻辑this.delegator = e => {        let currentNode = e.target;//目标节点const targetEventList = this.delegatorEvents[e.type];//如果当前目标节点等于事件当前所在的节点,不再向上冒泡while (currentNode !== e.currentTarget) {targetEventList.forEach(target => {if (currentNode.matches(target.matcher)) {//开始委托并把当前目标节点的event对象传过去target.callback.call(currentNode, e);}})currentNode = currentNode.parentNode;}}}/**绑定事件*@param event 绑定事件类型*@param selector 需要被代理的选择器*@param fn 触发函数* */on (event, selector, fn) {//相同事件只添加一次,如果存在,则再对应的代理事件里添加if (!this.delegatorEvents[event]) {this.delegatorEvents[event] = [{matcher: selector,callback: fn}]this.root.addEventListener(event, this.delegator);}else{this.delegatorEvents[event].push({matcher: selector,callback: fn})}return this;}/**移除事件*/destroy () {Object.keys(this.delegatorEvents).forEach(eventName => {this.root.removeEventListener(eventName, this.delegator)});}}root.Delegator = Delegator
}(window, document)

JS手动实现事件代理相关推荐

  1. js中的事件委托或是事件代理详解(转载)

    起因: 1.这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的: 2.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它 ...

  2. JS事件委托或者事件代理原理以及实现

    事件委托(事件代理)原理:简单的说就是将事件交由别人来执行,就是将子元素的事件通过冒泡的形式交由父元素来执行. 为什么要用时间委托? 在JavaScript中,添加到页面上的事件处理程序数量将直接关系 ...

  3. js事件流、事件代理等

    菜菜的自己发现真的啥都不太懂 - 虽然啥都会一点,但是却什么都不精通. 偶然看见js事件流和事件代理等 - 黑人问号脸,虽然在实际写代码的时候经常用到. 做个总结: 都是学的别人的. 事件代理:通过将 ...

  4. js事件委托或事件代理

    起因: 1.这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的: 2.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它 ...

  5. JS中的事件委托/事件代理详解

    起因: 1.这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的: 2.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它 ...

  6. JS中的事件委托 / 代理详解

    [前言] 事件委托/代理是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的 [主体] 概述: 那什么叫事件委托呢?它还有一个名字叫事件代理,JavaScript高级程序设计上讲:事件委托就是利用 ...

  7. JS 事件代理和事件委托

    目录 事件委托的概念理解 为什么要用事件委托 事件委托的原理: 事件代理(委托)实现 总结: 事件委托的概念理解 为什么叫事件委托?它还有一个名字叫事件代理. JavaScript高级程序设计上讲:事 ...

  8. js中的事件委托或是事件代理详解

    参考文章:https://www.cnblogs.com/liugang-vip/p/5616484.html 概述 事件委托也叫事件代理,JavaScript高级程序设计上讲:事件委托就是利用事件冒 ...

  9. JS的事件处理机制以及事件代理(事件委托)

    一.先记个小知识点.cssText cssText 本质:设置 HTML 元素的 style 属性值. 用法:document.getElementById("d1").style ...

最新文章

  1. linux输出信息打开tomcat,Linux下查看Tomcat的控制台输出信息
  2. Linux系统之创建逻辑卷
  3. Adaboost from Baidu
  4. Python-sys.argv[]用法
  5. php sorcket_PHP: Sockets - Manual
  6. 动态规划训练5 [回文词]
  7. 如何在驱动代码中中/dev目录内自动创建
  8. 安全维护上最不应该犯的十个基本错误
  9. 基于React的AmazeUI-touch使用(如何使用react)
  10. 什么是软件测试?软件测试的目的、意义是什么? 软件测试的流程是什么?
  11. 调研分析-全球与中国非线性光学BIBO晶体(BiB3O6)市场现状及未来发展趋势
  12. python开启一个简单的服务器
  13. zblog php 模板修改,ZBlog博客程序zblogPHP主题模板定制仿制修改
  14. Synchronized原理(偏向锁篇)
  15. java读取文件服务器文件,java读取远程服务器文件
  16. 金三银四,我为面试所准备的面试题,不看要遭老罪喽
  17. 基于 shell 的自动邮件任务监测器
  18. 六月计算机应用基础考试是啥,2017年6月计算机应用基础试题及答案
  19. VsCode安装和配置C++环境详细全流程
  20. C++ Qt C#文件夹重命名 C#复制文件(夹)

热门文章

  1. PS 学习笔记 14-历史记录画笔工具组
  2. Ubunut PPA源概述
  3. Gstore官网学习五:支持SPARQL查询语法
  4. 计算机视觉3-> yolov5目标检测1 |从入门到出土
  5. Sql server 查询指定时间区间工作日数、休息日数等日期操作
  6. Idea 使用git操作特别卡问题解决
  7. java-net-php-python-04海信集团售后管理系统计算机毕业设计程序
  8. 10 个 Java 安全最佳实践
  9. 当客户需求不明确时,怎么办?资深pm告诉你!
  10. 直线绘制算法-Bresenham算法