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 相关文章推荐
GWT中复制到剪贴板 js+flash实现复制 兼容性比较好
Mar 07 Javascript
基于jquery的inputlimiter 实现字数限制功能
May 30 Javascript
关于jQuery参考实例2.0 用jQuery选择元素
Apr 07 Javascript
node.js中的querystring.unescape方法使用说明
Dec 10 Javascript
JavaScript setTimeout使用闭包功能实现定时打印数值
Dec 18 Javascript
js+css实现回到顶部按钮(back to top)
Mar 02 Javascript
快速掌握Node.js模块封装及使用
Mar 21 Javascript
domReady的实现案例
Nov 23 Javascript
JavaScript Ajax实现异步通信
Dec 14 Javascript
Bootstrap禁用响应式布局的实现方法
Mar 09 Javascript
全面解析jQuery中的$(window)与$(document)的用法区别
Aug 15 jQuery
js 实现复选框只能选择一项的示例代码
Jan 23 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+MySql编写聊天室
2006/10/09 PHP
PHP Document 代码注释规范
2009/04/13 PHP
测试php连接mysql是否成功的代码分享
2014/01/24 PHP
用 Composer构建自己的 PHP 框架之基础准备
2014/10/30 PHP
控制打印时页眉角的代码
2007/02/08 Javascript
选择TreeView控件的树状数据节点的JS方法(jquery)
2010/02/06 Javascript
Js 去掉字符串中的空格(实现代码)
2013/11/19 Javascript
jQuery is()函数用法3例
2014/05/06 Javascript
javascript中拼接HTML字符串的最快、最好的方法
2014/06/07 Javascript
jQuery使用addClass()方法给元素添加多个class样式
2015/03/26 Javascript
基于MVC4+EasyUI的Web开发框架形成之旅之界面控件的使用
2015/12/16 Javascript
js+flash实现的5图变换效果广告代码(附演示与demo源码下载)
2016/04/01 Javascript
浅谈JQ中mouseover和mouseenter的区别
2016/09/13 Javascript
利用JS实现点击按钮后图片自动切换的简单方法
2016/10/24 Javascript
深入理解Node.js 事件循环和回调函数
2016/11/02 Javascript
AngularJS中run方法的巧妙运用
2017/01/04 Javascript
springmvc接收jquery提交的数组数据代码分享
2017/10/28 jQuery
详解使用React.memo()来优化函数组件的性能
2019/03/19 Javascript
JS实现的进制转换,浮点数相加,数字判断操作示例
2019/11/09 Javascript
JavaScript简单编程实例学习
2020/02/14 Javascript
创建与框架无关的JavaScript插件
2020/12/01 Javascript
[03:40]DOTA2抗疫特别篇《英雄年代》
2020/02/28 DOTA
Python简单连接MongoDB数据库的方法
2016/03/15 Python
python+selenium+autoit实现文件上传功能
2017/08/23 Python
解决python 输出是省略号的问题
2018/04/19 Python
Python 按字典dict的键排序,并取出相应的键值放于list中的实例
2019/02/12 Python
Pytorch 抽取vgg各层并进行定制化处理的方法
2019/08/20 Python
Linux系统下升级pip的完整步骤
2021/01/31 Python
HTML5 离线应用之打造零请求、无流量网站的解决方法
2013/04/25 HTML / CSS
ProBikeKit德国:在线公路自行车专家
2018/06/03 全球购物
英国现代家具和装饰网站:PN Home
2018/08/16 全球购物
个人求职信范文分享
2014/01/06 职场文书
红领巾广播站广播稿
2014/02/01 职场文书
白酒市场营销方案
2014/02/25 职场文书
派出所副所长四风问题个人整改措施思想汇报
2014/10/13 职场文书
捐款通知怎么写
2015/04/24 职场文书