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 相关文章推荐
jQuery 中关于CSS操作部分使用说明
Jun 10 Javascript
jquery和javascript中如何将一元素的内容赋给另一元素
Jan 09 Javascript
关于jQuery中的each方法(jQuery到底干了什么)
Mar 05 Javascript
jQuery实现简单网页遮罩层/弹出层效果兼容IE6、IE7
Jun 16 Javascript
js实现上一页下一页的效果【附代码】
Mar 10 Javascript
JavaScript必知必会(十) call apply bind的用法说明
Jun 08 Javascript
浅谈Angular的$q, defer, promise
Dec 20 Javascript
JavaScript比较同一天的时间大小实例代码
Feb 09 Javascript
Vuejs 实现简易 todoList 功能 与 组件实例代码
Sep 10 Javascript
小程序实现图片预览裁剪插件
Nov 22 Javascript
vue-router路由懒加载及实现的3种方式
Feb 28 Vue.js
用几道面试题来看JavaScript执行机制
Apr 30 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
THINKPHP+JS实现缩放图片式截图的实现
2010/03/07 PHP
PHP中substr_count()函数获取子字符串出现次数的方法
2016/01/07 PHP
PHP基于迭代实现文件夹复制、删除、查看大小等操作的方法
2017/08/11 PHP
jquery实现的超出屏幕时把固定层变为定位层的代码
2010/02/23 Javascript
js整数字符串转换为金额类型数据(示例代码)
2013/12/26 Javascript
学习javascript的闭包,原型,和匿名函数之旅
2015/10/18 Javascript
js调用webservice构造SOAP进行身份验证
2016/04/27 Javascript
Vue.Draggable实现拖拽效果
2020/07/29 Javascript
JS设置随机出现2个数字的实例代码
2017/07/19 Javascript
JS实现的Object数组去重功能示例【数组成员为Object对象】
2019/02/01 Javascript
vue中添加与删除关键字搜索功能
2019/10/12 Javascript
vue 使用async写数字动态加载效果案例
2020/07/18 Javascript
[53:10]Secret vs Pain 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
[54:30]Liquid vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
用实例详解Python中的Django框架中prefetch_related()函数对数据库查询的优化
2015/04/01 Python
Django分页功能的实现代码详解
2019/07/29 Python
用Python写一个自动木马程序
2019/09/17 Python
Pandas 解决dataframe的一列进行向下顺移问题
2019/12/27 Python
python标准库sys和OS的函数使用方法与实例详解
2020/02/12 Python
Django admin管理工具TabularInline类用法详解
2020/05/14 Python
通过自学python能找到工作吗
2020/06/21 Python
美国学校用品、教室和教学商店:Discount School Supply
2018/04/04 全球购物
正规的求职信范文分享
2013/12/11 职场文书
秸秆管理实施方案
2014/03/15 职场文书
民族团结先进个人事迹材料
2014/06/02 职场文书
室内趣味活动方案
2014/08/24 职场文书
安全环保演讲稿
2014/08/28 职场文书
工程部岗位职责
2015/02/10 职场文书
面试通知单大全
2015/04/20 职场文书
大学生饮品店创业计划书范文
2019/07/10 职场文书
六年级情感作文之500字
2019/10/23 职场文书
五年级作文之学校的四季
2019/12/05 职场文书
CSS 新特性 contain控制页面的重绘与重排问题
2021/04/30 HTML / CSS
pytorch 实现在测试的时候启用dropout
2021/05/27 Python
PostgreSQL13基于流复制搭建后备服务器的方法
2022/01/18 PostgreSQL
使用Nginx的访问日志统计PV与UV
2022/05/06 Servers