JavaScript事件委托的技术原理探讨示例


Posted in Javascript onApril 17, 2014

如今的JavaScript技术界里最火热的一项技术应该是‘事件委托(event delegation)'了。使用事件委托技术能让你避免对特定的每个节点添加事件监听器;相反,事件监听器是被添加到它们的父元素上。事件监听器会分析从子元素冒泡上来的事件,找到是哪个子元素的事件。基本概念非常简单,但仍有很多人不理解事件委托的工作原理。这里我将要解释事件委托是如何工作的,并提供几个纯JavaScript的基本事件委托的例子。

假定我们有一个UL元素,它有几个子元素:

<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元素可能会被删除,可能会有新增,监听它们的新增或删除事件将会是一场噩梦,尤其是当你的监听事件的代码放在应用的另一个地方时。但是,如果你将监听器安放到它们的父元素上呢?你如何能知道是那个子元素被点击了?

简单:当子元素的事件冒泡到父ul元素时,你可以检查事件对象的target属性,捕获真正被点击的节点元素的引用。下面是一段很简单的JavaScript代码,演示了事件委托的过程:

// 找到父元素,添加监听器... 
document.getElementById("parent-list").addEventListener("click",function(e) { 
// e.target是被点击的元素! 
// 如果被点击的是li元素 
if(e.target && e.target.nodeName == "LI") { 
// 找到目标,输出ID! 
console.log("List item ",e.target.id.replace("post-")," was clicked!"); 
} 
});

第一步是给父元素添加事件监听器。当有事件触发监听器时,检查事件的来源,排除非li子元素事件。如果是一个li元素,我们就找到了目标!如果不是一个li元素,事件将被忽略。这个例子非常简单,UL和li是标准的父子搭配。让我们试验一些差异比较大的元素搭配。假设我们有一个父元素div,里面有很多子元素,但我们关心的是里面的一个带有”classA” CSS类的A标记:
// 获得父元素DIV, 添加监听器... 
document.getElementById("myDiv").addEventListener("click",function(e) { 
// e.target是被点击的元素 
if(e.target && e.target.nodeName == "A") { 
// 获得CSS类名 
var classes = e.target.className.split(" "); 
// 搜索匹配! 
if(classes) { 
// For every CSS class the element has... 
for(var x = 0; x < classes.length; x++) { 
// If it has the CSS class we want... 
if(classes[x] == "classA") { 
// Bingo! 
console.log("Anchor element clicked!"); 
// Now do something here.... 
} 
} 
} 
} 
});

上面这个例子中不仅比较了标签名,而且比较了CSS类名。虽然稍微复杂了一点,但还是很具代表性的。比如,如果某个A标记里有一个span标记,则这个span将会成为target元素。这个时候,我们需要上溯DOM树结构,找到里面是否有一个 A.classA 的元素。

因为大部分程序员都会使用jQuery等工具库来处理DOM元素和事件,我建议大家都使用里面的事件委托方法,因为这里工具库里都提供了高级的委托方法和元素甄别方法。

希望这篇文章能帮助你理解JavaScript事件委托的幕后原理,希望你也感受到了事件委托的强大用处!

Javascript 相关文章推荐
JavaScript 设计模式之组合模式解析
Apr 09 Javascript
jQuery控制TR显示隐藏的几种方法
Jun 18 Javascript
轻松理解Javascript变量的相关问题
Jan 20 Javascript
vue.js整合vux中的上拉加载下拉刷新实例教程
Jan 09 Javascript
AjaxUpLoad.js实现文件上传功能
Mar 02 Javascript
Vue表单demo v-model双向绑定问题
Jun 29 Javascript
Vue-cli配置打包文件本地使用的教程图解
Aug 02 Javascript
前端防止用户重复提交js实现代码示例
Sep 07 Javascript
Vue.use()在new Vue() 之前使用的原因浅析
Aug 26 Javascript
Layui实现数据表格默认全部显示(不要分页)
Oct 26 Javascript
2分钟实现一个Vue实时直播系统的示例代码
Jun 05 Javascript
maptalks+three.js+vue webpack实现二维地图上贴三维模型操作
Aug 10 Javascript
JS实现div居中示例
Apr 17 #Javascript
淘宝网提供的国内NPM镜像简介和使用方法
Apr 17 #Javascript
js调用后台、后台调用前台等方法总结
Apr 17 #Javascript
JS下载文件|无刷新下载文件示例代码
Apr 17 #Javascript
你可能不知道的JavaScript的new Function()方法
Apr 17 #Javascript
在JS中解析HTML字符串示例代码
Apr 16 #Javascript
iframe的onreadystatechange事件在firefox下的使用
Apr 16 #Javascript
You might like
针对初学PHP者的疑难问答(2)
2006/10/09 PHP
php数据结构与算法(PHP描述) 查找与二分法查找
2012/06/21 PHP
使用dump函数,给php加断点测试
2013/06/25 PHP
php版微信开发Token验证失败或请求URL超时问题的解决方法
2016/09/23 PHP
jQuery Dialog 弹出层对话框插件
2010/08/09 Javascript
用dtree实现树形菜单 dtree使用说明
2011/10/17 Javascript
jQuery当鼠标悬停时放大图片的效果实例
2013/07/03 Javascript
button没写type=button会导致点击时提交
2014/03/06 Javascript
javascript制作的cookie封装及使用指南
2015/01/02 Javascript
jquery模拟实现鼠标指针停止运动事件
2016/01/12 Javascript
基于HTML模板和JSON数据的JavaScript交互(移动端)
2016/04/06 Javascript
jQuery模拟完美实现经典FLASH导航动画效果【附demo源码下载】
2016/11/09 Javascript
javascript ASCII和Hex互转的实现方法
2016/12/27 Javascript
vue进行图片的预加载watch用法实例讲解
2018/02/07 Javascript
Vue源码解读之Component组件注册的实现
2018/08/24 Javascript
微信小程序和H5页面间相互跳转代码实例
2019/09/19 Javascript
关于uniApp editor微信滑动问题
2021/01/15 Javascript
Python字符串中查找子串小技巧
2015/04/10 Python
python同时给两个收件人发送邮件的方法
2015/04/30 Python
django query模块
2019/04/20 Python
Django模板语言 Tags使用详解
2019/09/09 Python
python实现大学人员管理系统
2019/10/25 Python
python 3.8.3 安装配置图文教程
2020/05/21 Python
python删除文件、清空目录的实现方法
2020/09/23 Python
Opencv常见图像格式Data Type及代码实例
2020/11/02 Python
Yves Rocher捷克官方网站:植物化妆品的创造者
2019/07/31 全球购物
欧洲最古老的鞋厂:Peter Kaiser
2019/11/05 全球购物
护理专科自荐书范文
2014/02/18 职场文书
预备党员的自我评价
2014/03/12 职场文书
中式结婚主持词
2014/03/14 职场文书
兴趣班停课通知
2015/04/24 职场文书
大学文艺委员竞选稿
2015/11/19 职场文书
JavaScript中关于预编译、作用域链和闭包的理解
2021/03/31 Javascript
linux下导入、导出mysql数据库命令的实现方法
2021/05/26 MySQL
AJAX实现省市县三级联动效果
2021/10/16 Javascript
Mysql多层子查询示例代码(收藏夹案例)
2022/03/31 MySQL