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处理a标签超链接默认事件的方法
Jun 29 Javascript
js实现具有高亮显示效果的多级菜单代码
Sep 01 Javascript
BootStrap tooltip提示框使用小结
Oct 26 Javascript
jQuery模拟淘宝购物车功能
Feb 27 Javascript
jQuery插件Echarts实现的双轴图效果示例【附demo源码下载】
Mar 04 Javascript
js HTML5 canvas绘制图片的方法
Sep 08 Javascript
[原创]微信小程序获取网络类型的方法示例
Mar 01 Javascript
基于vue、react实现倒计时效果
Aug 26 Javascript
node 标准输入流和输出流代码实例
Sep 19 Javascript
Layui动态生成select下拉选择框不显示的解决方法
Sep 24 Javascript
js实现双人五子棋小游戏
May 28 Javascript
React 高阶组件HOC用法归纳
Jun 13 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
在IIS7.0下面配置PHP 5.3.2运行环境的方法
2010/04/13 PHP
Yii2使用dropdownlist实现地区三级联动功能的方法
2016/07/18 PHP
PHP导出带样式的Excel示例代码
2016/08/28 PHP
一些mootools的学习资源
2010/02/07 Javascript
Jquery 一次处理多个ajax请求的代码
2011/09/02 Javascript
jquery获取焦点和失去焦点事件代码
2013/04/21 Javascript
jQuery选择器简明总结(含用法实例,一目了然)
2014/04/25 Javascript
JavaScript 事件对象介绍
2015/04/13 Javascript
js文本框输入内容智能提示效果
2015/12/02 Javascript
JavaScipt选取文档元素的方法(推荐)
2016/08/05 Javascript
javascript cookie用法基础教程(概念,设置,读取及删除)
2016/09/20 Javascript
Bootstrap实现圆角、圆形头像和响应式图片
2016/12/14 Javascript
BootStrap table删除指定行的注意事项(笔记整理)
2017/02/05 Javascript
理解Angular的providers给Http添加默认headers
2017/07/04 Javascript
基于Cookie常用操作以及属性介绍
2017/09/07 Javascript
vuejs使用递归组件实现树形目录的方法
2017/09/30 Javascript
微信小程序实现导航栏选项卡效果
2020/06/19 Javascript
setTimeout与setInterval的区别浅析
2019/03/23 Javascript
create-react-app中添加less支持的实现
2019/11/15 Javascript
node.js 微信开发之定时获取access_token
2020/02/07 Javascript
vue props 单项数据流实例分享
2020/02/16 Javascript
[52:39]完美世界DOTA2联赛PWL S3 CPG vs Forest 第一场 12.16
2020/12/17 DOTA
python把ipynb文件转换成pdf文件过程详解
2019/07/09 Python
Python 通过微信控制实现app定位发送到个人服务器再转发微信服务器接收位置信息
2019/08/05 Python
pandas按行按列遍历Dataframe的几种方式
2019/10/23 Python
分享PyCharm的几个使用技巧
2019/11/10 Python
JAVA及PYTHON质数计算代码对比解析
2020/06/10 Python
canvas基础之图形验证码的示例
2018/01/02 HTML / CSS
Clearly澳大利亚:购买眼镜、太阳镜和隐形眼镜
2018/04/26 全球购物
网络事业创业计划书范文
2014/01/09 职场文书
在职员工证明书
2014/09/19 职场文书
领导班子专题民主生活会情况想汇报
2014/09/30 职场文书
房屋租赁合同协议书范本
2014/10/19 职场文书
教师节随笔
2015/08/15 职场文书
经典法律座右铭(50句)
2019/08/15 职场文书
详细介绍python操作RabbitMq
2022/04/12 Python