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 相关文章推荐
Mootools 1.2教程(2) DOM选择器
Sep 14 Javascript
取得窗口大小 兼容所有浏览器的js代码
Aug 09 Javascript
js DOM 元素ID就是全局变量
Sep 20 Javascript
flash调用js中的方法,让js传递变量给flash的办法及思路
Aug 07 Javascript
javascript实现完美拖拽效果
May 06 Javascript
javascript实现table表格隔行变色的方法
May 13 Javascript
Jquery全屏相册插件zoomvisualizer具有调节放大与缩小功能
Nov 02 Javascript
JS Array创建及concat()split()slice()的使用方法
Jun 03 Javascript
iOS + node.js使用Socket.IO框架进行实时通信示例
Apr 14 Javascript
php main 与 iframe 相互通讯类(js+php同域/跨域)
Sep 14 Javascript
详解性能更优越的小程序图片懒加载方式
Jul 18 Javascript
解决vue自定义组件@click点击失效问题
Apr 30 Vue.js
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
一键删除顽固的空文件夹 软件下载
2007/01/26 PHP
php下检测字符串是否是utf8编码的代码
2008/06/28 PHP
PHP调用Linux命令权限不足问题解决方法
2015/02/07 PHP
mod_php、FastCGI、PHP-FPM等PHP运行方式对比
2015/07/02 PHP
php的api数据接口书写实例(推荐)
2016/09/22 PHP
php类的自动加载操作实例详解
2016/09/28 PHP
iis6手工创建网站后无法运行php脚本的解决方法
2017/06/08 PHP
PHP+mysql实现的三级联动菜单功能示例
2019/02/15 PHP
PHP pthreads v3下同步处理synchronized用法示例
2020/02/21 PHP
javascript中substr,substring,slice.splice的区别说明
2010/11/25 Javascript
基于jquery的图片的切换(以数字的形式)
2011/02/14 Javascript
js中判断用户输入的值是否为空的简单实例
2013/12/23 Javascript
Javascript基础教程之函数对象和属性
2015/01/18 Javascript
js运动动画的八个知识点
2015/03/12 Javascript
动态生成的DOM不会触发onclick事件的原因及解决方法
2016/08/06 Javascript
WebPack基础知识详解
2017/01/16 Javascript
javaScript中封装的各种写法示例(推荐)
2017/07/03 Javascript
详解利用 Vue.js 实现前后端分离的RBAC角色权限管理
2017/09/15 Javascript
AngularJS 事件发布机制
2018/08/28 Javascript
CountUp.js数字滚动插件使用方法详解
2019/10/17 Javascript
微信小程序个人中心的列表控件实现代码
2020/04/26 Javascript
vue-cli3中配置alias和打包加hash值操作
2020/09/04 Javascript
[38:23]完美世界DOTA2联赛循环赛 FTD vs PXG BO2第二场 11.01
2020/11/02 DOTA
使用BeautifulSoup爬虫程序获取百度搜索结果的标题和url示例
2014/01/19 Python
Python中不同进制的语法及转换方法分析
2016/07/27 Python
Python内置模块hashlib、hmac与uuid用法分析
2018/02/12 Python
对Python+opencv将图片生成视频的实例详解
2019/01/08 Python
详解python中的异常和文件读写
2021/01/03 Python
CSS3中的display:grid,网格布局介绍
2019/10/30 HTML / CSS
一套C#面试题
2013/10/09 面试题
军训生自我鉴定范文
2013/12/27 职场文书
学习焦裕禄同志为人民服务思想汇报
2014/09/10 职场文书
廉洁自律承诺书范文
2015/04/28 职场文书
2015年乡镇残联工作总结
2015/05/13 职场文书
当幸福来敲门观后感
2015/06/01 职场文书
万能密码的SQL注入漏洞其PHP环境搭建及防御手段
2021/09/04 SQL Server