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 相关文章推荐
JQuery为textarea添加maxlength属性并且兼容IE
Apr 25 Javascript
javascript实现的一个带下拉框功能的文本框
May 08 Javascript
JavaScript让Textarea支持tab按键的方法
Jun 26 Javascript
jQuery实现的漂亮表单效果代码
Aug 18 Javascript
详解Javacript和AngularJS中的Promises
Feb 09 Javascript
基于Bootstrap的后台管理面板 Bootstrap Metro Dashboard
Jun 17 Javascript
jQuery中animate的几种用法与注意事项
Dec 12 Javascript
jQuery插件FusionCharts绘制的2D帕累托图效果示例【附demo源码】
Mar 28 jQuery
Angular 2父子组件之间共享服务通信的实现
Jul 04 Javascript
jQuery EasyUI的TreeGrid查询功能实现方法
Aug 08 jQuery
浅析Vue实例以及生命周期
Aug 14 Javascript
JavaScript原型对象原理与应用分析
Dec 27 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
在Debian系统下配置LNMP的教程
2015/07/09 PHP
详解Yii2 定制表单输入字段的标签和样式
2017/01/04 PHP
Yii框架实现多数据库配置和操作的方法
2017/05/25 PHP
PHP文件后缀不强制为.php方法
2019/03/31 PHP
Javascript 构造函数 实例分析
2008/11/26 Javascript
Javascript 继承机制的实现
2009/08/12 Javascript
用Javascript数组处理多个字符串的连接问题
2009/08/20 Javascript
javascript 按键事件(兼容各浏览器)
2013/12/20 Javascript
JavaScript中使用数组方法汇总
2016/02/16 Javascript
基于jquery fly插件实现加入购物车抛物线动画效果
2016/04/05 Javascript
jquery动态切换背景图片的简单实现方法
2016/05/14 Javascript
JavaScript登录验证码的实现
2016/10/27 Javascript
javascript实现获取图片大小及图片等比缩放的方法
2016/11/24 Javascript
vuejs开发组件分享之H5图片上传、压缩及拍照旋转的问题处理
2017/03/06 Javascript
JS实现多张图片预览同步上传功能
2017/06/23 Javascript
JS库中的Particles.js在vue上的运用案例分析
2017/09/13 Javascript
JavaScript new对象的四个过程实例浅析
2018/07/31 Javascript
在vue项目实现一个ctrl+f的搜索功能
2020/02/28 Javascript
[47:45]DOTA2-DPC中国联赛 正赛 Phoenix vs Dragon BO3 第一场 2月26日
2021/03/11 DOTA
python自动格式化json文件的方法
2015/03/11 Python
JSON Web Tokens的实现原理
2017/04/02 Python
python 用所有标点符号分隔句子的示例
2019/07/15 Python
django框架模型层功能、组成与用法分析
2019/07/30 Python
python twilio模块实现发送手机短信功能
2019/08/02 Python
Django使用Profile扩展User模块方式
2020/05/14 Python
从一次项目重构说起CSS3自定义变量在项目的使用方法
2021/03/01 HTML / CSS
世界上最大的网络主机公司:1&1
2016/10/12 全球购物
房屋产权共有协议书范本
2014/11/03 职场文书
师德标兵先进事迹材料
2014/12/19 职场文书
学校中秋节活动总结
2015/03/23 职场文书
西部计划志愿者工作总结
2015/08/11 职场文书
干货:我将这样书写我的演讲稿!
2019/05/09 职场文书
springboot拦截器无法注入redisTemplate的解决方法
2021/06/27 Java/Android
yyds什么意思?90后已经听不懂00后讲话了……
2022/02/03 杂记
SQL Server实现分页方法介绍
2022/03/16 SQL Server
Python实现科学占卜 让视频自动打码
2022/04/09 Python