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 DOM 学习第三章 内容表格
Feb 19 Javascript
Jquery ui css framework
Jun 28 Javascript
javascript各浏览器中option元素的表现差异
Apr 07 Javascript
页面图片浮动左右滑动效果的简单实现案例
Feb 10 Javascript
跟我学Node.js(四)---Node.js的模块载入方式与机制
Jun 04 Javascript
JavaScript实现为指定对象添加多个事件处理程序的方法
Apr 17 Javascript
javaScript 事件绑定、事件冒泡、事件捕获和事件执行顺序整理总结
Oct 10 Javascript
微信小程序遇到修改数据后页面不渲染的问题解决
Mar 09 Javascript
bootstrap table实现x-editable的行单元格编辑及解决数据Empty和支持多样式问题
Aug 10 Javascript
微信小程序获取手机号授权用户登录功能
Nov 09 Javascript
js 毫秒转天时分秒的实例
Nov 17 Javascript
Angular实现点击按钮后在上方显示输入内容的方法
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
PHP 和 XML: 使用expat函数(三)
2006/10/09 PHP
PHP限制页面只能在微信自带浏览器访问的代码
2014/01/15 PHP
微信公众平台开发教程⑥ 微信开发集成类的使用图文详解
2019/04/10 PHP
PHP-FPM 设置多pool及配置文件重写操作示例
2019/10/02 PHP
Valerio 发布了 Mootools
2006/09/23 Javascript
FLASH 广告之外的链接
2008/12/16 Javascript
jQuery Ajax异步处理Json数据详解
2013/11/05 Javascript
javascript确认框的三种使用方法
2013/12/17 Javascript
jQuery设置和获取HTML、文本和值示例
2014/07/08 Javascript
用canvas 实现个图片三角化(LOW POLY)效果
2016/02/18 Javascript
jQuery的Each比JS原生for循环性能慢很多的原因
2016/07/05 Javascript
javascript的几种写法总结
2016/09/30 Javascript
原生js调用json方法总结
2018/02/22 Javascript
使用VScode 插件debugger for chrome 调试react源码的方法
2019/09/13 Javascript
ES6 Object.assign()的用法及其使用
2020/01/18 Javascript
原生微信小程序开发中 redux 的使用详解
2021/02/18 Javascript
Python中的zipfile模块使用详解
2015/06/25 Python
python算法演练_One Rule 算法(详解)
2017/05/17 Python
在Python中实现替换字符串中的子串的示例
2018/10/31 Python
Python3获取电脑IP、主机名、Mac地址的方法示例
2019/04/11 Python
python接口调用已训练好的caffe模型测试分类方法
2019/08/26 Python
Python使用get_text()方法从大段html中提取文本的实例
2019/08/27 Python
PYTHON实现SIGN签名的过程解析
2019/10/28 Python
Python三元运算与lambda表达式实例解析
2019/11/30 Python
Python for i in range ()用法详解
2020/09/18 Python
一个入门级python爬虫教程详解
2021/01/27 Python
使用Python下载抖音各大V视频的思路详解
2021/02/06 Python
html5将图片转换成base64的实例代码
2016/09/21 HTML / CSS
英国的知名精品百货公司:House of Fraser(福来德)
2016/08/14 全球购物
毕业生个人投资创业计划书
2014/01/04 职场文书
大学生职业生涯规划范文
2014/01/22 职场文书
旷工检讨书1000字
2015/01/01 职场文书
服务行业标语口号
2015/12/26 职场文书
小学记事作文之200字
2019/08/06 职场文书
晶体管来复再生式二管收音机
2021/04/22 无线电
Python使用socket去实现TCP客户端和TCP服务端
2022/04/12 Python