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写一个鼠标拖动效果实现原理与代码
Dec 24 Javascript
Javascript 修改String 对象 增加去除空格功能(示例代码)
Nov 30 Javascript
JavaScript运行时库属性一览表
Mar 14 Javascript
jquery 隐藏与显示tr标签示例代码
Jun 06 Javascript
浅谈javascript对象模型和function对象
Dec 26 Javascript
Jquery对select的增、删、改、查操作
Feb 06 Javascript
JavaScript获取网页支持表单字符集的方法
Apr 02 Javascript
微信小程序 限制1M的瘦身技巧与方法详解
Jan 06 Javascript
MUI 实现侧滑菜单及其主体部分上下滑动的方法
Jan 25 Javascript
基于Vue实现的多条件筛选功能的详解(类似京东和淘宝功能)
May 07 Javascript
解决layui动态添加的元素click等事件触发不了的问题
Sep 20 Javascript
react 生命周期实例分析
May 18 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 编写的日历
2006/10/09 PHP
PHP转盘抽奖接口实例
2015/02/09 PHP
PHP实现的一致性哈希算法完整实例
2015/11/14 PHP
PHP超级全局变量【$GLOBALS,$_SERVER,$_REQUEST等】用法实例分析
2019/12/11 PHP
Vagrant(WSL)+PHPStorm+Xdebu 断点调试环境搭建
2019/12/13 PHP
?牟┛途W扣了一??效果出?? target=
2007/05/27 Javascript
JavaScript 模仿vbs中的 DateAdd() 函数的代码
2007/08/13 Javascript
Javascript实现的类似Google的Div拖动效果代码
2011/08/09 Javascript
js读写(删除)Cookie实例详解
2013/04/17 Javascript
JavaScript实现多维数组的方法
2013/11/20 Javascript
js/jquery解析json和数组格式的方法详解
2014/01/09 Javascript
浅谈javascript 迭代方法
2015/01/21 Javascript
js+html5实现的自由落体运动效果代码
2016/01/28 Javascript
基于JavaScript实现轮播图代码
2016/07/14 Javascript
Move.js入门
2017/02/08 Javascript
web前端vue之vuex单独一文件使用方式实例详解
2018/01/11 Javascript
在微信小程序里使用watch和computed的方法
2018/08/02 Javascript
微信小程序scroll-view实现滚动穿透和阻止滚动的方法
2018/08/20 Javascript
用js限制网页只在微信浏览器中打开(或者只能手机端访问)
2020/12/24 Javascript
一文读懂vue动态属性数据绑定(v-bind指令)
2020/07/20 Javascript
JavaScript实现弹出窗口效果
2020/12/09 Javascript
Vue如何跨组件传递Slot的实现
2020/12/14 Vue.js
vue 在单页面应用里使用二级套嵌路由
2020/12/19 Vue.js
[01:46]DOTA2上海特锦赛小组赛英文解说KotlGuy采访
2016/02/27 DOTA
Python中二维列表如何获取子区域元素的组成
2017/01/19 Python
解决Django模板无法使用perms变量问题的方法
2017/09/10 Python
解决pycharm启动后总是不停的updating indices...indexing的问题
2019/11/27 Python
在spyder IPython console中,运行代码加入参数的实例
2020/04/20 Python
解决运行django程序出错问题 'str'object has no attribute'_meta'
2020/07/15 Python
HTML5触摸事件演化tap事件介绍
2016/03/25 HTML / CSS
Clarria化妆品官方网站:购买天然和有机化妆品系列
2018/04/08 全球购物
大学生演讲稿
2014/04/25 职场文书
个人担保书格式范文
2014/05/12 职场文书
安全生产知识竞赛活动总结
2014/07/07 职场文书
机票销售员态度不好检讨书
2014/09/27 职场文书
工作会议简报
2015/07/20 职场文书