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的eval JSON object问题
Nov 15 Javascript
jquery ajax方式直接提交整个表单核心代码
Aug 15 Javascript
为什么JS中eval处理JSON数据要加括号
Apr 13 Javascript
JS获取复选框的值,并传递到后台的实现方法
May 30 Javascript
Angular的MVC和作用域
Dec 26 Javascript
vue中用H5实现文件上传的方法实例代码
May 27 Javascript
vue项目实战总结篇
Feb 11 Javascript
通过封装scroll.js 获取滚动条的值
Jul 13 Javascript
vue使用Font Awesome的方法步骤
Feb 26 Javascript
使用node-media-server搭建一个简易的流媒体服务器
Jan 20 Javascript
Vue 集成 PDF.js 实现 PDF 预览和添加水印的步骤
Jan 22 Vue.js
javascript对象3个属性特征
Nov 17 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边学边教》(04.编写简易的通讯录――视频教程1)
2006/12/13 PHP
PHP运行时强制显示出错信息的代码
2011/04/20 PHP
apache php模块整合操作指南
2012/11/16 PHP
php中的路径问题与set_include_path使用介绍
2014/02/11 PHP
php curl请求信息和返回信息设置代码实例
2015/04/27 PHP
设置下载不需要倒计时cookie(倒计时代码)
2008/11/19 Javascript
jquery pagination插件实现无刷新分页代码
2009/10/13 Javascript
js获取select默认选中的Option并不是当前选中值
2014/05/07 Javascript
基于jQuery的判断iPad、iPhone、Android是横屏还是竖屏的代码
2014/05/11 Javascript
Bootstrap所支持的表单控件实例详解
2016/05/16 Javascript
js提交form表单,并传递参数的实现方法
2016/05/25 Javascript
js中获取 table节点各tr及td的内容简单实例
2016/10/14 Javascript
微信小程序实现发微博功能的示例代码
2020/06/24 Javascript
在Vuex中Mutations修改状态操作
2020/07/24 Javascript
vue 图片裁剪上传组件的实现
2020/11/12 Javascript
JavaScript async/await原理及实例解析
2020/12/02 Javascript
[01:04:32]DOTA2-DPC中国联赛 正赛 Aster vs LBZS BO3 第二场 2月23日
2021/03/11 DOTA
Python常用模块介绍
2014/11/21 Python
python Flask实现restful api service
2017/12/04 Python
使用Python快速搭建HTTP服务和文件共享服务的实例讲解
2018/06/04 Python
python 函数的缺省参数使用注意事项分析
2019/09/17 Python
Django实现基于类的分页功能
2019/10/31 Python
win10下python2和python3共存问题解决方法
2019/12/23 Python
python+selenium定时爬取丁香园的新型冠状病毒数据并制作出类似的地图(部署到云服务器)
2020/02/09 Python
解决Django中checkbox复选框的传值问题
2020/03/31 Python
浅析Python 条件控制语句
2020/07/15 Python
HTML5中判断用户是否正在浏览页面的方法
2014/05/03 HTML / CSS
HTML5 表单验证失败的提示语问题
2017/07/13 HTML / CSS
英国健身专家:WIT Fitness
2021/02/09 全球购物
演讲主持词
2014/03/18 职场文书
汽车运用工程专业求职信
2014/06/18 职场文书
2014年工程部工作总结
2014/11/25 职场文书
干货:如何写好观后感 !
2019/05/21 职场文书
基于Redis位图实现用户签到功能
2021/05/08 Redis
关于MybatisPlus配置双数据库驱动连接数据库问题
2022/01/22 Java/Android
Redis如何使用乐观锁(CAS)保证数据一致性
2022/03/25 Redis