javascript中的事件代理初探


Posted in Javascript onMarch 08, 2014

事件在javascript中一直是最强大的对象之一。javascript提供了addEventListener和attachEvent两个方法来为DOM节点绑定事件,jquery作了进一步封装,提供了兼容各个浏览器的bind方法。现在来看,这种传统的事件绑定方式存在着以下不足:

1.可能需要绑定很多的EventHander。

假如页面中某个表有100行,现在必须为每一行绑定一个click事件。那么就必须绑定100个EventHandler,这对页面性能来说有着极大的负担,因为需要创建更多的内存来存放这些Handler。

2.事件无法绑定后加入的DOM节点。

假如页面中的代码如下:

$("#dv").bind('click',function(){alert('test');});
$(body).append('<div id="dv">test</div>')

后加入的div是无法触发点击事件的。

为了解决这两个问题,javascript引入了事件代理(event proxy)。首先,我们了解一下js中的冒泡机制。

javascript中的事件代理初探


基本上所有的浏览器都支持事件冒泡。当在某个DOM节点上触发事件上,事件会一直向上传递,一直到文档的根节点。既然所有的节点的事件最终都会传递到文档根节点,那么我们如果直接将事件绑定到文档根节点(document节点),然后通过event.target来判断是哪个节点触发的事件,是不是减少很多EventHandler的绑定呢?

jquery中的live方法正式根据这个原理来实现的,下面我们来实现一个live简单版:

$.fn.mylive=function(eventType,fn){
 var that=this.selector;
 $(document).bind(eventType,function(event){
  var match=$(event.target).closest(that)
  if(match.length !== 0){
   fn.apply($(event.target),[event]);
  }
 })
}
$("#tb td").mylive('click',function(event){
 alert(event.target.innerHTML);
});
var tb='<table id="tb"> \
  <tr> \
   <td>the first column</td>\
   <td>the second column</td>\
   <td>the third column</td>\
  </tr>\
</table>';
$("body").append(tb);

live方法中,事件绑定在document节点上,$(event.target).closest(that)来匹配真正触发事件的元素。demo中,我们为每个后加入的td都绑定了click事件,单击不同的td,我们发现会弹出他们对应Text的提示框。

live方法弥补了前面提到的传统事件绑定方法的两个不足。但live方法仍存在它的不足之处。看这句代码:

$("#tb td").mylive('click',function(event){
 alert(event.target.innerHTML);
});

它会首先根据jquery选择器遍历整个文档,找到所有的#tb td元素,将他们存储成对象。然而,在live的实现方法中,并没有利用这些对象,而仅仅是将"#td td"作为字符串与事件源进行匹配而已。这就大大增加了很多无谓的消耗。

那么有没有办法改善这一状况呢?jquery中提供了delegate代理方法,它支持将事件绑定到指定的元素上,而不仅仅是document上。了解了它的原理,我们来实现一个delegate简单版:

$(body).append('<div id="dv"></div>');
$.fn.mydelegate=function(selector,eventType,fn){
 $(this).bind(eventType,function(event){
  var match=$(event.target).closest(selector);
  if(match.length !== 0){
   fn.apply($(event.target),[event]);
  }
 });
}
$("#dv").mydelegate('td','click',function(event){
 alert(event.target.innerHTML);
});
var tb='<table id="tb"> \
  <tr> \
   <td>the first column</td>\
   <td>the second column</td>\
   <td>the third column</td>\
  </tr>\
</table>';
$("dv").append(tb);

mydeletage方法不需要获取所有的td对象,而仅仅只需要获取绑定事件的div对象。这在执行效率上要优于live方法。

这里仅仅起到一个抛砖引玉的作用,让大家了解到事件代理的原理而已,jquery中的live和delegate实现要复杂的多。

Javascript 相关文章推荐
TBCompressor js代码压缩
Jan 05 Javascript
jQuery1.6 类型判断实现代码
Sep 01 Javascript
用Jquery选择器计算table中的某一列某一行的合计
Aug 13 Javascript
jQuery里filter()函数与find()函数用法分析
Jun 24 Javascript
详解前端构建工具gulpjs的使用介绍及技巧
Jan 19 Javascript
JavaScript队列的应用实例详解【经典数据结构】
Apr 12 Javascript
关于在mongoose中填充外键的方法详解
Aug 14 Javascript
总结js函数相关知识点
Feb 27 Javascript
详解Vue webapp项目通过HBulider打包原生APP
Jun 29 Javascript
详解小程序不同页面之间通讯的解决方案
Nov 23 Javascript
ionic使用angularjs表单验证(模板验证)
Dec 12 Javascript
JavaScript动态添加数据到表单并提交的几种方式
Jun 26 Javascript
jquery实现弹出div,始终显示在屏幕正中间的简单实例
Mar 08 #Javascript
Extjs表单常见验证小结
Mar 07 #Javascript
extJS中常用的4种Ajax异步提交方式
Mar 07 #Javascript
禁用JavaScript控制台调试的方法
Mar 07 #Javascript
jquery日历控件实现方法分享
Mar 07 #Javascript
jquery.form.js用法之清空form的方法
Mar 07 #Javascript
jquery设置按钮停顿3秒不可用
Mar 07 #Javascript
You might like
建立文件交换功能的脚本(三)
2006/10/09 PHP
PHP安装攻略:常见问题解答(三)
2006/10/09 PHP
PHP 多维数组排序实现代码
2009/08/05 PHP
PHP使用GETDATE获取当前日期时间作为一个关联数组的方法
2015/03/19 PHP
YII CLinkPager分页类扩展增加显示共多少页
2016/01/29 PHP
PHP微信模板消息操作示例
2017/06/29 PHP
解决php extension 加载顺序问题
2019/08/16 PHP
php封装实现钉钉机器人报警接口的示例代码
2020/08/08 PHP
js parsefloat parseint 转换函数
2010/01/21 Javascript
return false,对阻止事件默认动作的一些测试代码
2010/11/17 Javascript
jQuery实现自动切换播放的经典滑动门效果
2015/09/12 Javascript
js密码强度校验
2015/11/10 Javascript
javascript运算符——位运算符全面介绍
2016/07/14 Javascript
Jquery on绑定的事件 触发多次实例代码
2016/12/08 Javascript
vue实现列表的添加点击
2016/12/29 Javascript
jQuery选择器实例应用
2017/01/05 Javascript
Angular 5.x 学习笔记之Router(路由)应用
2018/04/08 Javascript
AngularJS实现的base64编码与解码功能示例
2018/05/17 Javascript
vscode中vue-cli项目es-lint的配置方法
2018/07/30 Javascript
vue 项目build错误异常的解决方法
2019/04/22 Javascript
Python读写Excel文件的实例
2013/11/01 Python
python抓取网页内容示例分享
2014/02/24 Python
python实现ip查询示例
2014/03/26 Python
Python实现PS滤镜特效Marble Filter玻璃条纹扭曲效果示例
2018/01/29 Python
python实现对象列表根据某个属性排序的方法详解
2019/06/11 Python
Django3.0 异步通信初体验(小结)
2019/12/04 Python
Python 读取 YUV(NV12) 视频文件实例
2019/12/09 Python
使用Python爬虫库requests发送请求、传递URL参数、定制headers
2020/01/25 Python
Omio中国:全欧洲低价大巴、火车和航班搜索和比价
2018/08/09 全球购物
高级护理实习生自荐信
2013/09/28 职场文书
汽车工程专业应届生求职信
2013/10/19 职场文书
整改落实情况汇报材料
2014/10/29 职场文书
2015年学校保卫部工作总结
2015/05/11 职场文书
QT与javascript交互数据的实现
2021/05/26 Javascript
python元组打包和解包过程详解
2021/08/02 Python
vue二维数组循环嵌套方式 循环数组、循环嵌套数组
2022/04/24 Vue.js