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>

效果如下:

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


微信号: love_skills

越努力,越幸运!越幸运,越努力!

做上CEO不是梦

赢取白富美不是梦

屌丝逆袭不是梦

就是现在!!加油

js事件委托的方式绑定详解的更多相关文章

  1. 异步加载JS的4种方式(详解)

    方案1:$(document).ready <!DOCTYPE html> <html> <head> <script src="http://co ...

  2. 黄聪:异步加载JS的4种方式(详解)

    方案1:$(document).ready <!DOCTYPE html> <html> <head> <script src="http://co ...

  3. JS中的函数节流throttle详解和优化

    JS中的函数节流throttle详解和优化在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(mousemove),这种事件有一个特点,在一个正常的操作中,有可能在一个短的 ...

  4. 彻底弄懂JS事件委托的概念和作用

    一.写在前头    接到某厂电话问什么是事件代理的时候,一开始说addEventListener,然后他说直接绑定新的元素不会报dom不存在的错误吗?然后我就混乱了,我印象中这个方法是可以绑定新节点的 ...

  5. js事件委托

    什么是事件委托:通俗的讲,onclick,onmouseover,onmouseout,等就是事件,委托呢,就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这个事件. 也 ...

  6. Vue通信、传值的多种方式,详解

    Vue通信.传值的多种方式,详解 转自:https://blog.csdn.net/qq_35430000/article/details/79291287 一.通过路由带参数进行传值 ①两个组件 A ...

  7. js插件---videojs中文文档详解

    js插件---videojs中文文档详解 一.总结 一句话总结: js插件网上都有很多参考资料,使用起来也非常简单 二.lavarel中使用实例 <video id="example_ ...

  8. JS事件委托的原理和应用

    js事件委托也叫事件代理,实际上事件委托就是通过事件冒泡实现的,所谓的事件就是onclick,onmouseover,ondown等等,那么委托呢?委托就是指本来这个事是要你自己做的,但是你却让别人帮 ...

  9. JS JSOP跨域请求实例详解

    JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题.这篇文章主要介绍了JS JSOP跨域请求实例详解的相关资料,需要的朋友可以参考下 ...

随机推荐

  1. 设置 java -jar 的进程显示名称

    有时候我们会用 nohup java -jar xxx.jar来将一些可执行的java application挂在后台,类似windows服务一样来运行.但是有一个不爽的地方,在linux终端里用jp ...

  2. 【6年开源路】海王星给你好看!FineUI v4.0正式版暨《FineUI3to4一键升级工具》发布!

    去年10-28号,我发布了一篇文章<海王星给你好看!FineUI v4.0公测版发布暨<你找BUG我送书>活动开始>,标志着FineUI开始向4.0版本迈进.经过4个月3个公测 ...

  3. 一个看似很简单的SQL却难倒了很多人

    一个选课表,有学生id,课程id,老师id,要求选出同时选了语文和数学的学生 USE [tempschool] GO /****** 对象: Table [dbo].[SelectC] 脚本日期: 0 ...

  4. [BZOJ1016][JSOI2008]最小生成树计数(结论题)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1016 分析: 首先有个性质:如果边集E.E'都可以表示一个图G的最小生成树(当然E和E ...

  5. 在eclipse中使用第三方库总结

    一.建立user library 导入第三方jar文件,最简单的方式是:右键工程/属性/java build path/add external jars. 另一种方式是:window/prefren ...

  6. [jQuery EasyUI系列] 创建增删改查应用

    一.数据收集并妥善管理数据是网络应用共同的必要.CRUD允许我们生产页面列表并编辑数据库记录. 本文主要演示如何使用jQuery EasyUI实现CRUD DataGrid. 将使用到的插件有: da ...

  7. chgrp 简明笔记

    改变与文件相关联的组 chgrp [options] group file-list 参数 group 为新组的名称或者数值ID,file-list 为要改变其相关联组的文件路径名列表 选项 -c   ...

  8. 微信公众平台消息接口开发之微信浏览器HTTP_USER_AGENT判断

    在微信公众平台的开发过程中,我们有时需要开发网页并判断是否是是来自微信浏览器访问,本文介绍如何做出这一判断. 一.$_SERVER数组 $_SERVER 是一个包含了诸如头信息(header).路径( ...

  9. Cause: org.apache.ibatis.reflection.ReflectionException: Could not set property 'orderdetails' of 'class com.luchao.mybatis.first.po.Orders' with value 'Orderdetail [id=null, ordersId=3, itemsId=1, it

    从上面异常的解释来看是因为反射不能将Orders设置到orderdetails属性上,仔细检查了MyBatis的配置文件,发现: <collection property="order ...

  10. 理解 Paxos

    Paxos是前段时间刚获得图灵奖的大神Leslie Lamport所提出的,是用来解决分布式系统中的一致性问题的算法.该算法对于分布式系统的重要性,在这里不再赘言.了解过Paxos的朋友应该都知道,要 ...