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 相关文章推荐
css transform 3D幻灯片特效实现步骤解读
Mar 27 Javascript
jquery索引在使用中的一些困惑
Oct 24 Javascript
Jquery插件分享之气泡形提示控件grumble.js
May 20 Javascript
javascript中sort() 方法使用详解
Aug 30 Javascript
jquery实现右侧栏菜单选择操作
Mar 04 Javascript
JS实现仿PS的调色板效果完整实例
Dec 21 Javascript
Vue 短信验证码组件开发详解
Feb 14 Javascript
Bootstrap treeview实现动态加载数据并添加快捷搜索功能
Jan 07 Javascript
Vue 中的compile操作方法
Feb 26 Javascript
vue轮播图插件vue-concise-slider的使用
Mar 13 Javascript
node.js 基于 STMP 协议和 EWS 协议发送邮件
Feb 14 Javascript
vue router 动态路由清除方式
May 25 Vue.js
个人总结的一些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
星际中的相关伤害
2020/03/04 星际争霸
一个简洁的多级别论坛
2006/10/09 PHP
php中看实例学正则表达式
2006/12/25 PHP
UCenter Home二次开发指南
2009/05/28 PHP
PHP使用FFmpeg获取视频播放总时长与码率等信息
2016/09/13 PHP
javascript中将Object转换为String函数代码 (json str)
2012/04/29 Javascript
javascript 实现 秒杀,团购 倒计时展示的记录 分享
2013/07/12 Javascript
javascript中clone对象详解
2014/12/03 Javascript
学习JavaScript设计模式之责任链模式
2016/01/18 Javascript
详解AngularJS 模态对话框
2016/04/07 Javascript
jQuery EasyUI中的日期控件DateBox修改方法
2016/11/09 Javascript
AngularJS框架的ng-app指令与自动加载实现方法分析
2017/01/04 Javascript
微信小程序 详解页面跳转与返回并回传数据
2017/02/13 Javascript
使用webpack搭建react开发环境的方法
2018/05/15 Javascript
[08:54]DOTA2-DPC中国联赛 正赛 Aster vs LBZS 选手采访
2021/03/11 DOTA
机器学习python实战之决策树
2017/11/01 Python
用TensorFlow实现lasso回归和岭回归算法的示例
2018/05/02 Python
python中多层嵌套列表的拆分方法
2018/07/02 Python
python使用循环打印所有三位数水仙花数的实例
2018/11/13 Python
解决python打不开文件(文件不存在)的问题
2019/02/18 Python
Python任务自动化工具tox使用教程
2020/03/17 Python
Python使用20行代码实现微信聊天机器人
2020/06/05 Python
浅析python中的del用法
2020/09/02 Python
python爬虫调度器用法及实例代码
2020/11/30 Python
Python抖音快手代码舞(字符舞)的实现方法
2021/02/07 Python
CSS3区域模块region相关编写示例
2015/08/28 HTML / CSS
用CSS3的box-reflect来制作倒影效果
2016/11/15 HTML / CSS
德国著名廉价网上药店:Shop-Apotheke
2017/07/23 全球购物
荷兰多品牌网上鞋店:Stoute Schoenen
2017/08/24 全球购物
《小壁虎借尾巴》教学反思
2014/02/16 职场文书
技术总监管理职责范本
2014/03/06 职场文书
纪念九一八事变演讲稿:忘记意味着背叛
2014/09/14 职场文书
教师先进事迹材料
2014/12/16 职场文书
2015年清明节演讲稿范文
2015/03/17 职场文书
竞聘书的秘诀
2019/04/02 职场文书
图文详解nginx日志切割的实现
2022/01/18 Servers