javascript 中的事件委托详解


Posted in Javascript onOctober 25, 2016

这几天看到一个面试题,大概就是,让你给1000个li都添加一个click事件,应该怎么添加?大多数人第一开始的感觉可能就是,每个li上边都添加一个呗,那要是这样的话,估计面试的时候就会GG了,这里就是撤出了我们的事件冒泡和捕获机制,以及事件委托机制,对于上边这些,我们慢慢来看.

首先说一下事件冒泡和事件捕获机制,事件冒泡是有微软公司提出来的,事件捕获是有网景公司提出来的,当时两家是争论的不可开交,后来w3c也没办法,就采取了折中的方式,事件产生后先捕获后冒泡,

通常,在js中监听事件的方法共有三种,分别是:

  ele.addEventListener(type,listener,[useCapture]);//IE6~8不支持

ele.attachEvent('on'+type,listener);//IE6~10支持,IE11不支持

ele.onClick=function(){};//所有浏览器都支持

w3c规范中定义了三个事件阶段,依次是捕获阶段,目标阶段,冒泡阶段,而w3c指定的dom2级规定中,使用的是addEventListener来监听事件的.所以我们就以addEventListener来讲解,首先事假冒泡就像你从往水中扔一块石子,水中的气泡从下边往上冒一样,意思为触发事件后从子元素王父元素方向触发,而捕获机制则正好相反,捕获机制是从父元素往子元素方向进行事件触发,而addEventListener函数中的第三位参数正是来决定是使用捕获机制还是冒泡机制的,当useCapture为true是为捕获机制,当useCapture为false时是冒泡机制,我们看一下例子:

复制代码

<div class="parent">
  <div class="child">

  </div>
</div>
<script>
  var parent = document.getElementsByClassName('parent')[0];
  var child = document.getElementsByClassName('child')[0];

  parent.addEventListener('click',function(){
    console.log("这里是父元素");
  },false);
  child.addEventListener('click',function(){
    console.log("这里是子元素");
  },false);
</script>

javascript 中的事件委托详解

当我们点击子元素是显示上图,当我们将false改为true后就会发现执行顺序会反过来,这就是事件冒泡和捕获的区别,他们两个刚好相反,

javascript 中的事件委托详解

那么使用这种绑定机制我们的弊端在于要去给每一个对象绑定事件会是一个特别麻烦的事情,当我们要删除一个事件或者要改变一个事件的时候会特别的繁琐,更重要的是,我们增加了JavaScript和dom节点之间的关联,而且一点出现循环引用,很有可能造成内存泄露,这些都是它的弊端,

 

那么解决这种弊端的一种方法就是事件代理(event delegation),这个方法可以让你避免去给每一个节点一一的添加事件,它的做法是将这些监听事件去绑定到这些节点的父元素上,在父元素上的这个监听函数自动去判断是哪一个子元素触发的事件,从而可以对触发事件的子元素进行操作,这里我们给出的例子是davidwalsh所给出的一个例子:

 

现在我们有一个父元素ul和几个li子元素,

<ul id="parent-list">
  <li id="post-1">Item 1</li>
  <li id="post-2">Item 2</li>
  <li id="post-3">Item 3</li>
  <li id="post-4">Item 4</li>
  <li id="post-5">Item 5</li>
  <li id="post-6">Item 6</li>
</ul>

现在我们要实现的是,当我们点击每一个li节点的时候,都会输出li节点中的内容,按照上边的写法,你可以选中这些li,让后给他们加上这些方法,然后等到不需要了再将他们移除,如果有100个li,1000个li呢,这将会成为你的噩梦,较好的解决方法就是给父元素添加一个监听事件,之后的问题便是怎么去判断出来时哪一个li被点击了? 我们可以在监听事件中去判断当前event的target来判断是否是我们要找的节点,这里我们有一个简单的例子:

// 找到父元素,绑定一个监听事件
document.getElementById("parent-list").addEventListener("click", function(e) {
  // e.target是点击的元素
  // 如果它是li元素
  if(e.target && e.target.nodeName == "LI") {
    //
    console.log("List item ", e.target.id.replace("post-", ""), " was clicked!");
  }
});

当ul中发生点击事件后,因为addEventListener默认是冒泡事件,所以监听事件会在底层事件冒泡过来时执行,在触发了事件后,去检测是否是我们要寻找的目标元素,如果不是,就会忽略过去,那我们不仅仅可以通过目标元素的标签是不是我们需要的目标元素,我们还可以根据目标元素的属性或者类名来进行检测,利用ele.maeches这个API来进行处理,

document.getElementById("myDiv").addEventListener("click",function(e) {
  // e.target 就是当前被点击的元素
 if (e.target && e.target.matches("a.classA")) {
  console.log("Anchor element clicked!");
  }
});

因此我们可以看得出来,使用事件代理这种方式,能够给我们带来很多的便捷,可以避免很多坑,使用事件代理是一种很强大的方法.

          感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
jquery实用代码片段集合
Aug 12 Javascript
jquery在项目中做复选框时遇到的一些问题笔记
Nov 17 Javascript
在javascript中如何得到中英文混合字符串的长度
Jan 17 Javascript
让人蛋疼的JavaScript语法特性
Sep 30 Javascript
常用jQuery代码分享
Jul 14 Javascript
JS+CSS实现鼠标滑过时动态翻滚的导航条效果
Sep 24 Javascript
百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换
Feb 19 Javascript
JavaScript 数组的深度复制解析
Nov 02 Javascript
利用Plupload.js解决大文件上传问题, 带进度条和背景遮罩层
Mar 15 Javascript
JS原生带缩略图的图片切换效果
Oct 10 Javascript
webpack4 SplitChunks实现代码分隔详解
May 23 Javascript
ES6 proxy和reflect的使用方法与应用实例分析
Feb 15 Javascript
js实现控制textarea输入字符串的个数,鼠标按下抬起判断输入字符数
Oct 25 #Javascript
分分钟玩转Vue.js组件
Oct 25 #Javascript
谈谈target=_new和_blank的不同之处
Oct 25 #Javascript
js实现上传图片预览方法
Oct 25 #Javascript
微信小程序(应用号)开发新闻客户端实例
Oct 24 #Javascript
微信小程序 倒计时组件实现代码
Oct 24 #Javascript
微信小程序 WXDropDownMenu组件详解及实例代码
Oct 24 #Javascript
You might like
PHP 高手之路(一)
2006/10/09 PHP
php仿discuz分页效果代码
2008/10/02 PHP
ThinkPHP框架安全实现分析
2016/03/14 PHP
PHP基于迭代实现文件夹复制、删除、查看大小等操作的方法
2017/08/11 PHP
这段js代码得节约你多少时间
2011/12/20 Javascript
jquery动画3.创建一个带遮罩效果的图片走廊
2012/08/24 Javascript
js 剪切板应用clipboardData详细解析
2013/12/17 Javascript
javascript学习指南之回调问题
2016/04/23 Javascript
深入理解JavaScript中的浮点数
2016/05/18 Javascript
js css+html实现简单的日历
2016/07/14 Javascript
Bootstrap基本样式学习笔记之表格(2)
2016/12/07 Javascript
使用淘宝镜像cnpm安装Vue.js的图文教程
2018/05/17 Javascript
Node.js Koa2使用JWT进行鉴权的方法示例
2018/08/17 Javascript
小程序实现列表多个批量倒计时
2021/01/29 Javascript
JS实现随机抽选获奖者
2019/11/07 Javascript
浅谈Vue.js之初始化el以及数据的绑定说明
2019/11/14 Javascript
js实现盒子滚动动画效果
2020/08/09 Javascript
微信小程序中data-key属性之数据传输(经验总结)
2020/08/22 Javascript
[01:10:49]Secret vs VGJ.S 2018国际邀请赛淘汰赛BO3 第二场 8.24
2018/08/25 DOTA
Python3里的super()和__class__使用介绍
2015/04/23 Python
浅谈Python的垃圾回收机制
2016/12/17 Python
python 利用文件锁单例执行脚本的方法
2019/02/19 Python
浅谈pycharm使用及设置方法
2019/09/09 Python
python3发送request请求及查看返回结果实例
2020/04/30 Python
Python 使用Opencv实现目标检测与识别的示例代码
2020/09/08 Python
美国一家专业的太阳镜网上零售商:Solstice太阳镜
2016/07/25 全球购物
StubHub新加坡:购买和出售全球活动门票
2017/03/10 全球购物
土木工程个人自荐信范文
2013/11/30 职场文书
大专生的学习自我评价
2013/12/04 职场文书
专科应届毕业生求职信
2014/06/04 职场文书
给客户的感谢信
2015/01/21 职场文书
教代会开幕词
2015/01/28 职场文书
公司开会通知
2015/04/20 职场文书
无房证明样本
2015/06/17 职场文书
2019年新郎保证书3篇
2019/10/17 职场文书
vue点击弹窗自动触发点击事件的解决办法(模拟场景)
2021/05/25 Vue.js