javascript事件委托的方式绑定详解

 更新时间:2024年09月02日 17:05:24   投稿:hebedich  
我们在学习JavaScript中,难免都会去网上查一些资料,也许偶尔就会遇到“事件委托”,但是,大多数时说的是“事件绑定”,对于“事件委托”,或是不提,或是浅尝辄止,对于我这个比较好奇的人来说,实在很头疼,尤其是想更多的了解“事件委托”的时候

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>

效果如下:

再看看事件的绑定情况,跟我们绑定事件的情况一致:

以上所述就是本文的全部内容了,希望大家能够喜欢。

相关文章

  • js中点击空白区域时文本框与隐藏层的显示与影藏问题

    js中点击空白区域时文本框与隐藏层的显示与影藏问题

    文本框获得焦点的时在文本框的下方显示一个浮动层,点击文本框隐藏浮动层,下面为大家介绍下鼠标点击时文本框与隐藏层处理问题,感兴趣的朋友可以参考下
    2013-08-08
  • JS实现网页端猜数字小游戏

    JS实现网页端猜数字小游戏

    这篇文章主要为大家详细介绍了JS实现网页端猜数字小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • JS实现左边列表移到到右边列表功能

    JS实现左边列表移到到右边列表功能

    这篇文章主要介绍了JS实现左边列表移到到右边列表功能,实现功能主要是左边的下拉框内容添加到右边的下拉框,支持多选移动,且同时将右边的下拉框对象移除,需要的朋友可以参考下
    2018-03-03
  • Echarts读取动态数据完整代码

    Echarts读取动态数据完整代码

    这篇文章主要给大家介绍了关于Echarts读取动态数据的相关资料,使用Echarts画图时,数据一般不是静态写死的,而是通过后端接口动态获取的,需要的朋友可以参考下
    2023-10-10
  • jquery插件bootstrapValidator数据验证详解

    jquery插件bootstrapValidator数据验证详解

    这篇文章主要为大家详细介绍了jquery插件bootstrapValidator数据验证使用教程,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • 微信小程序之导航滑块视图容器功能的实现代码(简单两步)

    微信小程序之导航滑块视图容器功能的实现代码(简单两步)

    这篇文章主要介绍了微信小程序之导航滑块视图容器功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • JavaScript实现的圆形浮动标签云效果实例

    JavaScript实现的圆形浮动标签云效果实例

    这篇文章主要介绍了JavaScript实现的圆形浮动标签云效果,涉及javascript字符串与数组的遍历、排序操作以及元素样式动态操作与数学运算等相关技巧,是非常实用的一段代码,需要的朋友可以参考下
    2015-08-08
  • Javascript BOM学习小结(六)

    Javascript BOM学习小结(六)

    BOM:BrowserObjectModel,浏览器对象模型,提供JS中对浏览器的各种操作的对象,是JS应用中唯一没有相关标准的部分,这事BOM经常出现问题的所在,主要用于处理浏览器窗口与框架,浏览器特有的JS扩展也被默认为BOM的一部分,而各浏览器之间的公有对象就成了默认的标准
    2015-11-11
  • 让html元素随浏览器的大小自适应垂直居中的实现方法

    让html元素随浏览器的大小自适应垂直居中的实现方法

    下面小编就为大家带来一篇让html元素随浏览器的大小自适应垂直居中的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-10-10
  • 用javascript关闭本窗口技巧小结

    用javascript关闭本窗口技巧小结

    window.close()是用来关闭窗口的,而且ie和firefox都是支持的,下面通过示例为大家介绍下用javascript关闭本窗口
    2014-09-09

最新评论