javascript事件委托的方式绑定详解


Posted in Javascript onJune 10, 2015

js事件绑定

事件绑定,这里使用了冒泡的原理,从点击的元素开始,递归方式的向父元素传播事件,这样做的好处是对于大量要处理的元素,不必为每个元素都绑定事件,只需要在他们的父元素上绑定一次即可,提高性能。还有一个好处就是可以处理动态插入dom中的元素,直接绑定的方式是不行的。

之前一直使用的是jquery的on方法做这样的事情,前几天看到公司项目中有实现这种方式的源代码,拿来仔细研究研究,跟大家分享分享。

function $bindAction(dom, event, listeners) {
 #这里的dom为绑定事件的元素,比如document.body
 #event为绑定的事件,比如click
 #listeners是待执行的事件对象
 $addEvent(dom, event, function(e) {
 #这里获取事件e
 #获取点击的元素src
 var e = e || window.event,
  src = e.target || e.srcElement,
  action,
  returnVal;

 #模拟冒泡的方式,先是src,然后是src.parentNode,再然后是src.parentNode.parent.Node
 #当前dom元素等于事件绑定的dom元素的时候,停止“冒泡”
 while (src && src !== dom) {
  #循环获取dom元素的attr-action属性,
  action = src.getAttribute('attr-action');
  #如果当前dom元素存在attr-action属性,并且事件对象中有该属性值的函数,执行这个函数
  #将事件e、当前dom元素、元素的属性attr-action值传给要执行的函数
  if (listeners[action]) {
  returnVal = listeners[action]({
   src : src,
   e : e,
   action : action
  });
  #如果上面的函数执行之后返回false,停止继续“冒泡”
  if (returnVal === false) {
   break;
  }
  }
  #获取当前dom元素的父元素节点
  src = src.parentNode;
 }
 });
};

function $addEvent(obj, type, handle) {
 if(!obj || !type || !handle) {
 return;
 }
 #绑定事件到多个对象,递归调用
 if( obj instanceof Array) {
 for(var i = 0, l = obj.length; i < l; i++) {
  $addEvent(obj[i], type, handle);
 }
 return;
 }
 #绑定多个事件,递归调用
 if( type instanceof Array) {
 for(var i = 0, l = type.length; i < l; i++) {
  $addEvent(obj, type[i], handle);
 }
 return;
 }
 #下面这一大段用来记录当前页面一共绑定了多少个事件,以及事件的相关信息
 #以及某个对象上面绑定的事件id
 window.__allHandlers = window.__allHandlers || {};
 window.__Hcounter = window.__Hcounter || 0;
 function setHandler(obj, type, handler, wrapper) {
 obj.__hids = obj.__hids || [];
 var hid = 'h' + ++window.__Hcounter;
 obj.__hids.push(hid);
 window.__allHandlers[hid] = {
  type : type,
  handler : handler,
  wrapper : wrapper
 }
 }
 #这个里面的apply是为了修改绑定事件所执行函数中的this
 #这个在低版本的IE中才真正起作用
 function createDelegate(handle, context) {
 return function() {
  return handle.apply(context, arguments);
 };
 }

 #绑定事件,记录事件绑定信息
 if(window.addEventListener) {
 var wrapper = createDelegate(handle, obj);
 setHandler(obj, type, handle, wrapper)
 obj.addEventListener(type, wrapper, false);
 }
 else if(window.attachEvent) {
 var wrapper = createDelegate(handle, obj);
 setHandler(obj, type, handle, wrapper)
 obj.attachEvent("on" + type, wrapper);
 }
 else {
 obj["on" + type] = handle;
 }
};

看个例子:

当点击前三个的时候会依次弹出classname,其他的都不会触发事件

<style type="text/css">
#out{width: 500px;background-color: #CDE}
#inner{background-color: #ABCDEF;margin: 0;padding: 0;width: 400px;}
ul{background-color: pink;margin: 0;padding: 0;width: 400px;}
li{width:398px;height: 20px;border: 1px solid black;margin: 15px 0px;padding: 0px;list-style: none;}  
</style>
div#out > div#inner :
<div id="out">
 <ul id="inner">
 <li class="lia" attr-action="setWhat">class="lia" attr-action="setWhat"</li>
 <li class="lia" attr-action="setWhat">class="lia" attr-action="setWhat"</li>
 <li class="lib" attr-action="setWhat">class="lia" attr-action="setWhat"</li>
 <li class="lib">class="lib"</li>
 <li class="lib">class="lib"</li>
 <li class="lib">class="lib"</li>
 </ul>
</div>
ul :
<ul>
 <li class="lia" attr-action="setWhat">class="lia" attr-action="setWhat"</li>
 <li class="lia" attr-action="setWhat">class="lia" attr-action="setWhat"</li>
 <li class="lib" attr-action="setWhat">class="lia" attr-action="setWhat"</li>
 <li class="lib">class="lib"</li>
 <li class="lib">class="lib"</li>
 <li class="lib">class="lib"</li>
</ul>

<script>
listeners = {
 setWhat : function(opts) {
 alert(opts.src.className);
 return false;
 },
};
window.onload = function(){$bindAction(document.getElementById('out'), ['click', 'mouseover'], listeners);}
</script>

效果如下:

javascript事件委托的方式绑定详解

再看看事件的绑定情况,跟我们绑定事件的情况一致:

javascript事件委托的方式绑定详解

以上所述就是本文的全部内容了,希望大家能够喜欢。

Javascript 相关文章推荐
javascript 写类方式之四
Jul 05 Javascript
js 分栏效果实现代码
Aug 29 Javascript
jQuery bind事件使用详解
May 05 Javascript
jquery固定底网站底部菜单效果
Aug 13 Javascript
jquery控制表单输入框显示默认值的方法
May 22 Javascript
在AngularJS中使用jQuery的zTree插件的方法
Apr 21 Javascript
jquery获取img的src值的简单实例
May 17 Javascript
从重置input file标签中看jQuery的 .val() 和 .attr(“value”) 区别
Jun 12 Javascript
AngularJS 路由详解和简单实例
Jul 28 Javascript
解决npm管理员身份install时出现权限的问题
Mar 16 Javascript
详解angular路由高亮之RouterLinkActive
Apr 28 Javascript
如何在CocosCreator里画个炫酷的雷达图
Apr 16 Javascript
个人总结的一些JavaScript技巧、实用函数、简洁方法、编程细节
Jun 10 #Javascript
浅析JavaScript动画
Jun 10 #Javascript
JavaScript操作XML文件之XML读取方法
Jun 09 #Javascript
JavaScript检查数字是否为整数或浮点数的方法
Jun 09 #Javascript
jQuery取消ajax请求的方法
Jun 09 #Javascript
JavaScript动态添加style节点的方法
Jun 09 #Javascript
jQuery实现将页面上HTML标签换成另外标签的方法
Jun 09 #Javascript
You might like
php和jquery实现地图区域数据统计展示数据示例
2014/02/12 PHP
PHP开发中AJAX技术的简单应用
2015/12/11 PHP
PHP生成可点击刷新的验证码简单示例
2016/05/13 PHP
PHP设计模式(八)装饰器模式Decorator实例详解【结构型】
2020/05/02 PHP
js change,propertychange,input事件小议
2011/12/20 Javascript
JQuery页面的表格数据的增加与分页的实现
2013/12/10 Javascript
Windows系统下使用Sublime搭建nodejs环境
2015/04/13 NodeJs
深入讲解AngularJS中的自定义指令的使用
2015/06/18 Javascript
javascript 广告移动特效的实现代码
2016/06/25 Javascript
Node.js开发教程之基于OnceIO框架实现文件上传和验证功能
2016/11/30 Javascript
nodejs个人博客开发第二步 入口文件
2017/04/12 NodeJs
JavaScript箭头函数_动力节点Java学院整理
2017/06/28 Javascript
VUE axios发送跨域请求需要注意的问题
2017/07/06 Javascript
vue-cli初始化项目中使用less的方法
2018/08/09 Javascript
jQuery实现的简单日历组件定义与用法示例
2018/12/24 jQuery
vue 动态组件用法示例小结
2020/03/06 Javascript
Ajax获取node服务器数据的完整步骤
2020/09/20 Javascript
[00:32]2018DOTA2亚洲邀请赛VG出场
2018/04/03 DOTA
[01:20]2018DOTA2亚洲邀请赛总决赛战队LGD晋级之路
2018/04/07 DOTA
[48:46]完美世界DOTA2联赛PWL S2 SZ vs FTD.C 第二场 11.19
2020/11/19 DOTA
详解Python3中的Sequence type的使用
2015/08/01 Python
Python建立Map写Excel表实例解析
2018/01/17 Python
Python中的并发处理之asyncio包使用的详解
2018/04/03 Python
python2.7 安装pip的方法步骤(管用)
2019/05/05 Python
python scrapy爬虫代码及填坑
2019/08/12 Python
python3实现在二叉树中找出和为某一值的所有路径(推荐)
2019/12/26 Python
CSS3径向渐变之大鱼吃小鱼之孤单的大鱼
2016/04/26 HTML / CSS
HTML5实践-图片设置成灰度图
2012/11/12 HTML / CSS
骆驼官方商城:CAMEL
2016/11/22 全球购物
P D PAOLA意大利官网:西班牙著名的珠宝首饰品牌
2019/09/24 全球购物
老师给学生的表扬信
2014/01/17 职场文书
酒店总经理职务说明书
2014/02/26 职场文书
后备干部培训方案
2014/05/22 职场文书
啤酒节策划方案
2014/05/28 职场文书
党员教师批评与自我批评发言稿
2014/10/15 职场文书
JS实现简单的九宫格抽奖
2022/06/28 Javascript