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 相关文章推荐
js apply/call/caller/callee/bind使用方法与区别分析
Oct 28 Javascript
jquery 3D球状导航的文章分类
Jul 06 Javascript
Jquery动态更改一张位图的src与Attr的使用
Jul 31 Javascript
JavaScript事件学习小结(五)js中事件类型之鼠标事件
Jun 09 Javascript
AngularJS自定义插件实现网站用户引导功能示例
Nov 07 Javascript
jQuery模拟完美实现经典FLASH导航动画效果【附demo源码下载】
Nov 09 Javascript
巧妙运用v-model实现父子组件传值的方法示例
Apr 07 Javascript
js作用域和作用域链及预解析
Apr 11 Javascript
Vue CLI2升级至Vue CLI3的方法步骤
May 20 Javascript
Vue简单实现原理详解
May 07 Javascript
基于postman获取动态数据过程详解
Sep 08 Javascript
Vue使用路由钩子拦截器beforeEach和afterEach监听路由
Nov 16 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框架的性能
2008/01/10 PHP
ThinkPHP实现带验证码的文件上传功能实例
2014/11/01 PHP
php格式化金额函数分享
2015/02/02 PHP
php $_SESSION会员登录实例分享
2021/01/19 PHP
PHP+Apache+Mysql环境搭建教程
2016/08/01 PHP
PHP实现的网站目录扫描索引工具
2016/09/08 PHP
php实现的简单数据库操作Model类
2016/11/16 PHP
use jscript with List Proxy Server Information
2007/06/11 Javascript
JavaScript中的类继承
2010/11/25 Javascript
Javascript this 的一些学习总结
2012/08/31 Javascript
url参数中有+、空格、=、%、&amp;、#等特殊符号的问题解决
2013/05/15 Javascript
控制input输入框中提示信息的显示和隐藏的方法
2014/02/12 Javascript
jQuery ajax时间差导致的变量赋值问题分析
2016/01/22 Javascript
Bootstrap前端开发案例一
2016/06/17 Javascript
js 获取站点应用名的简单实例
2016/08/18 Javascript
Vue.js实现模拟微信朋友圈开发demo
2017/04/20 Javascript
vue教程之toast弹框全局调用示例详解
2020/08/24 Javascript
vue2.0s中eventBus实现兄弟组件通信的示例代码
2017/10/25 Javascript
layui 根据后台数据动态创建下拉框并同时默认选中的实例
2019/09/02 Javascript
详解vuejs中执行npm run dev出现页面cannot GET/问题
2020/04/26 Javascript
python实现带声音的摩斯码翻译实现方法
2015/05/20 Python
Python入门学习之字符串与比较运算符
2015/10/12 Python
python的构建工具setup.py的方法使用示例
2017/10/23 Python
Python Django中间件使用原理及流程分析
2020/06/13 Python
Python大批量搜索引擎图像爬虫工具详解
2020/11/16 Python
美国一家运动专业鞋类零售商:Warehouse Shoe Sale(WSS)
2018/03/28 全球购物
CheapTickets泰国:廉价航班,查看促销价格并预订机票
2019/12/28 全球购物
土木工程建筑专业毕业生求职信
2013/10/21 职场文书
护士的岗位职责
2013/12/04 职场文书
关爱女孩行动实施方案
2014/03/13 职场文书
标准单位租车协议书
2014/09/23 职场文书
2014年小学英语教师工作总
2014/12/03 职场文书
2014幼儿教师个人工作总结
2014/12/03 职场文书
2015教师年度考核评语
2015/03/25 职场文书
Springboot集成kafka高级应用实战分享
2022/08/14 Java/Android