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 相关文章推荐
发一个自己用JS写的实用看图工具实现代码
Jul 26 Javascript
jQuery使用数组编写图片无缝向左滚动
Dec 11 Javascript
javascript:void(0)使用探讨
Aug 27 Javascript
jQuery过滤选择器:not()方法使用介绍
Apr 20 Javascript
不想让浏览器运行javascript脚本的方法
Nov 20 Javascript
JavaScript的removeChild()函数用法详解
Dec 27 Javascript
jQuery时间验证和转换为标准格式的时间格式
Mar 06 Javascript
Vue实现购物车功能
Apr 27 Javascript
微信小程序canvas写字板效果及实例
Jun 15 Javascript
微信小程序HTTP接口请求封装的实现
Feb 21 Javascript
小程序实现新用户判断并跳转激活的方法
May 20 Javascript
JavaScript Canvas编写炫彩的网页时钟
Oct 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原理之错误抑制与内嵌HTML分析
2011/05/02 PHP
ThinkPHP基本的增删查改操作实例教程
2014/08/22 PHP
php将textarea数据提交到mysql出现很多空格的解决方法
2014/12/19 PHP
codeigniter发送邮件并打印调试信息的方法
2015/03/21 PHP
php面向对象值单例模式
2016/05/03 PHP
php PDO判断连接是否可用的实现方法
2017/04/03 PHP
自己的js工具_Form 封装
2009/08/21 Javascript
Javascript 刷新全集常用代码
2009/11/22 Javascript
jQuery中需要注意的细节问题小结
2011/12/06 Javascript
js读写cookie实现一个底部广告浮层效果的两种方法
2013/12/29 Javascript
jQuery截取指定长度字符串的实现原理及代码
2014/07/01 Javascript
浅析Node.js中的内存泄漏问题
2015/06/23 Javascript
如何使用jquery easyui创建标签组件
2015/11/18 Javascript
js html css实现复选框全选与反选
2016/10/09 Javascript
微信小程序 页面跳转如何实现传值
2017/04/05 Javascript
基于vue写一个全局Message组件的实现
2019/08/15 Javascript
vue 解除鼠标的监听事件的方法
2019/11/13 Javascript
jQuery实现查看图片功能
2020/12/01 jQuery
[49:35]2018DOTA2亚洲邀请赛3月30日 小组赛A组 KG VS TNC
2018/03/31 DOTA
py中的目录与文件判别代码
2008/07/16 Python
Python的类实例属性访问规则探讨
2015/01/30 Python
Python中super()函数简介及用法分享
2016/07/11 Python
python实现日常记账本小程序
2018/03/10 Python
对python读写文件去重、RE、set的使用详解
2018/12/11 Python
新手入门学习python Numpy基础操作
2020/03/02 Python
python selenium自动化测试框架搭建的方法步骤
2020/06/14 Python
浅谈opencv自动光学检测、目标分割和检测(连通区域和findContours)
2020/06/04 Python
python如何删除文件、目录
2020/06/23 Python
Pycharm新手使用教程(图文详解)
2020/09/17 Python
Opencv+Python识别PCB板图片的步骤
2021/01/07 Python
整理HTML5中表单的常用属性及新属性
2016/02/19 HTML / CSS
暑期培训随笔感言
2014/03/10 职场文书
道德之星事迹材料
2014/05/03 职场文书
介绍信怎么写
2015/01/30 职场文书
管理人员岗位职责
2015/02/14 职场文书
小组口号霸气押韵
2015/12/24 职场文书