javascript之事件绑定
曾经写过一篇随笔,attachEvent和addEventListener,跟本文内容有很多相似之处
本文链接:javascript之事件绑定
1、原始写法
<div onclick="alert('you clicked me just now);'">click me</div>
在刚开始学习前端的时候,我们不免这么将事件绑定写在html中,后来我们想将html和js脚本进行分离便这么写
<div id="test">click me</div>
<script type="text/javascript">
test.onclick=function(){
alert("you click me just now");
};
</script>
这么写其实和上一种写法在执行上是没有任何分别的,只是他略微显得“高大上”一点。在此,需要感谢八楼@con的提醒,其实他们还是有一点点的区别,因为它们的执行环境是稍微有点不同的,其函数作用域中包含的对象是不一样的。详情可看本文的留言。
当我们写更复杂一些的脚本的时候,发现这种“对象.事件=事件处理函数”方式并不好,因为后面的事件明显得会覆盖前一个事件处理函数,多次事件绑定的结果往往是仅执行最后一个事件处理函数,可以看attachEvent和addEventListener文中示例。
后来,我们必须在实际开发中放弃这种“非主流”的写法了。
2.attachEvent和addEventListener
首先得说明,attachEvent是仅在万恶的IE是下可行的,addEventListener是在其它遵循W3C标准的浏览器中可行(常用的浏览器可以放心使用addEventListener),并且在IE9和之后的版本中也可以使用addEventListener。看来在大势所趋下,MS不得不妥协了。
在此得说明,上述的无论是“对象.事件=事件处理函数”的方式,attachEvent事件绑定的方式还是addEventListener不带第三个参数的情形下,都是冒泡型事件处理方式。至于什么是冒泡事件什么是捕获事件,这个涉及到DOM文档对象模型和事件流。简单来说就是,冒泡就是事件的传播方式是从事件目标节点到DOM文档结构的根节点方向传播,而捕获型事件就是从DOM文档结构的根节点到事件目标节点。
obj = document.getElementById("testdiv");
obj.attachEvent('onclick',function(){{alert('1');});
obj.attachEvent('onclick',function(){{alert('2');});
obj.attachEvent('onclick',function(){{alert('3');});
//执行顺序是alert(3),alert(2),alert(1);
obj = document.getElementById("testdiv");
obj.addEventListener('click',function(){{alert('1');},false);
obj.addEventListener('click',function(){{alert('2');},false);
obj.addEventListener('click',function(){{alert('3');},false);
//点击obj对象时,执行顺序为alert('1'),alert('2'),alert('3');
从这段例子可以看出:
对于同一个DOM对象绑定多个事件处理函数时,attachEvent是先绑定后执行,而addEventListener是先绑定先执行,这么看来attachEvent绑定的事件不符合程序员开发的思路啊,我后绑定的事件处理函数却要先执行,完全不遵循“先来后到”的规矩,搞得莫名其妙,看来这个attachEvent在不远的将来应该会被淘汰。
attachEvent在事件绑定的事件还必须加上这个“on”,如果不注意的话很容易忘记添加,这个“on”关键字可能是从那种原始写法中没有进化完全吧。
当了解完了这两个函数的区别后,我们可以写一些共同方法用来兼容IE和其它的浏览器
function addEvent(elm, evType, fn, useCapture)
{
if (elm.addEventListener)
{
elm.addEventListener(evType, fn, useCapture); // W3C标准,根据useCapture来判断是冒泡事件还是捕获事件
return true;
}
else if (elm.attachEvent)
{
var r = elm.attachEvent(‘on‘ + evType, fn);//IE5+,仅支持冒泡事件
return r;
}
else
{
elm['on' + evType] = fn;//DOM事件
}
}
当然这个方法也有弊端,在IE8跟之前版本下,还是事件的后绑定先执行且一直都是冒泡事件。或者使用如下的方法:
var addEvent = (function () {
if (document.addEventListener) {
return function (el, type, fn) {
if (el.length) {
for (var i = 0; i && el.length; i++) {
addEvent(el[i], type, fn);
}
} else {
el.addEventListener(type, fn, false);
}
};
} else {
return function (el, type, fn) {
if (el.length) {
for (var i = 0; i && el.length; i++) {
addEvent(el[i], type, fn);
}
} else {
el.attachEvent('on' + type, function () {
return fn.call(el, window.event);
});
}
};
}
})();
这些都是原生的脚本事件绑定处理方式,显得低调有内涵。
继续
<div id="a1" style="float: left; width: 200px; height: 200px; background-color: red;">
a1
<div id="a2" style="float: left; width: 100px; height: 100px; background-color: blue;">a2</div>
</div>
<script type="text/script">
a1.addEventListener('click', function (e) {
console.log('a1');
});
a2.addEventListener('click', function (e) {
console.log('a2');
e.stopPropagation();
});
</script>
在a2的事件处理函数中添加了e.stopPropagation(),这句代码可以阻止事件的继续传播(无论是继续捕获阶段还是继续冒泡阶段),在实际开发中应该会经常性的用到,IE还是不支持。Event.preventDefault()可以阻止事件目标的默认动作,IE也是不支持的。
3.jQ的bind,delegate,on和live
有了jQ之后,所有的事件绑定都变得轻而易举了。bind,delegate,on和live他们的使用在此就不做赘述,jQ api上都有详细讲解。
首先说bind,bind已经很好的解决了IE的attachEvent先绑定后执行的问题了,请看
<div id="a1" style="float: left; width: 200px; height: 200px; background-color: red;">
a1
</div>
<script src="jquery-1.10.2.js" type="text/javascript"></script>
<script type="text/javascript">
$('#a1').bind('click', function () { console.log('1'); }).bind('click', function () { console.log('2'); });
</script>
点击a1后,打出的log是先1后2,跟事件的绑定顺序一致。
在jQ1.7之前的版本中,bind方法会直接将事件处理函数附加到元素上,而事件处理函数被添加到当前元素的jQuery对象上,当有很多元素绑定时间处理函数时,这时便需要大量的存储空间来存储这个事件处理函数了。那个时候,推荐使用的方法是live,因为live是将事件处理函数添加document对象上,因此可以省去为每个元素都附加存储事件处理函数的空间。
不过,jQ1.7之后的版本中,有了on方法,live方法也就被取消了,on方法将事件处理函数添加到了当前选定的jQuery对象上。其实它等价于delegate方法。
<ul id="ul">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<ul>
<script type='text/javascript'>
$('#ul').on('mouseover','li',function(){alert('1');});
</script>
上例中,将事件处理函数function(){alert('1');}附加到的对象就是ul。
delegate是事件委托,因为是委托,事件绑定在ul上,动态在ul里添加的元素也能激发上述绑定的事件处理函数
<script type='text/javascript'>
$('#ul').delegate('li','mouseover',function(){alert('1');});
</script>
看一下jQ源码就知道,delegate等价于on方法。
delegate: function( selector, types, data, fn ) {
return this.on( types, selector, data, fn );
},
综上所述,在jQ中推荐的事件绑定方式是delegate、on,它们是等价的,在1.7之后的版本中live方法不可以使用,bind方法也可以绑定事件,但是最好是简单元素结构下使用bind。
4.关于事件处理函数的移除
<div id="test">aaa</div>
<script type="text/javascript">
test.onclick = function(){alert('1')};
test.onclick = null;
</script>
这种方式其实就是覆盖。
针对于attachEvent和addEventListener两个函数,他们的解除方法分别是detachEvent和removeEventListener
obj = document.getElementById("testdiv");
obj.detachEvent('onclick',function(){{alert('1');});
obj.detachEvent('onclick',function(){{alert('2');});
obj.detachEvent('onclick',function(){{alert('3');});
obj = document.getElementById("testdiv");
obj.removeEventListener('click',function(){{alert('1');},false);
obj.removeEventListener('click',function(){{alert('2');},false);
obj.removeEventListener('click',function(){{alert('3');},false);
对于jQ的事件解除绑定分别是
bind---->unbind
on---->off
live---->die
delegate---->undelegate
等等
为了防止jQ事件解除的时候将所有的方法都给解除了,可以给事件绑定时添加命名空间来区分
$element.delegate('.boot','click.dismiss.modal',fn1)
.delegate('.boot','dblclick.dismiss',fn2)
.delegate('.boot','mouseover',fn3);
//do sth
$element.undelegate('.modal');//仅将fn1解除绑定
//do sth
$element.undelegate('.dismiss');//能够将fn1和fn2都解除绑定,但fn1已经解除 ,此处实现的效果是解除fn2
//do sth
$element.undelegate(); //解除所有事件,此处仅解除fn3
另外,如果我们想方法绑定后仅执行一次的话,可以使用jQ的one方法,省去我们解除事件绑定的过程。
$element.one('dblclcik',function(){
// do sth
});
// 可以省去解绑这个过程,仅能执行一次
事件绑定的方式很多,需要看时机过程中的需求,需要考虑的因素是简便,简介,性能好,同时需要兼容各种浏览器,做到这些就可以以不变应万变了。
本文参考:attachEvent和addEventListener
全文中如果有不正确的地方,请斧正。
javascript之事件绑定的更多相关文章
- javascript对象事件绑定方法
javascript对象事件绑定方法 今天在做对象事件绑定的过程中出现了一点异外情况,由于事件方法是由参数传过来的,需要将当前对象call过去,方便方法体里直接调用this 错误写法 obj.oncl ...
- jQuery 事件绑定 和 JavaScript 原生事件绑定
总结一下:jQuery 事件绑定 和 JavaScript 原生事件绑定 及 区别 jQuery 事件绑定 jQuery 中提供了四种事件监听绑定方式,分别是 bind.live.delegate.o ...
- 关于JavaScript的事件绑定
js事件绑定的几种方式 JavaScript中有三种常用的绑定事件方法: 1. 在DOM元素中直接绑定: 2. 在JavaScript代码中绑定: 3. 绑定事件佳妮婷函数. 一.在DOM元素中直接绑 ...
- JavaScript的事件绑定及深入
事件绑定分为两种:一种是传统事件绑定(内联模型,脚本模型),一种是现代事件绑定 (DOM2 级模型).现代事件绑定在传统绑定上提供了更强大更方便的功能. 一.传统事件绑定的问题传统事件绑定有内联模型 ...
- JavaScript之事件绑定多个序列执行方法
//一种事件绑定多个方法:以加载事件为例 function addEventLoad(func,isLog) { var oldOnLoad = window.onload; if (typeof w ...
- javascript 的事件绑定和取消事件
研究fabricjs中发现,它提供canvas.on('mousemove', hh) 来绑定事件, 提供 canvas.off()来取消绑定事件这样的接口,很是方便, 那我们就不妨探究一下内在的实现 ...
- JavaScript 中事件绑定的三种方式
以下是在 JS 中事件绑定的三种方式. 1. HTML onclick attribute <button type="button" id="uplo ...
- JavaScript中事件绑定的方法总结
最近收集了一些关于JavaScript绑定事件的方法,汇总了一下,不全面,但是,希望便于以后自己查看. JavaScript中绑定事件的方法主要有三种: 1 在DOM元素中直接绑定 2 JavaScr ...
- JavaScript中事件绑定的三种方式
JavaScript使得网页与用户友好交互,在使用 js 进行时间绑定的时候有三种绑定方式. 第一种:初学者以及普通写法 <div id="dom0"> <inp ...
随机推荐
- sqlalchemy--group_concat的使用
今天,一个app客户端同事需要我服务器端提供一组数据,这组数据要按类分好,把整个结构都展示给他,他直接使用就可以了.数据大概如下面这种: 同事需要的结构大概就是类型1有多少,分别是什么;类型2有多少, ...
- C语言+ODBC+SQL 连接
第一步:配置ODBC. ①.在控制面板找到ODBC,或者在控制面板上搜索ODBC.如图: ②.点击ODBC的添加按钮,选择SQL Server,这是会出现创建SQL Server的新数据源的对话框,我 ...
- T-SQL表联接查询
由于实践不足,总是忘记SQL Server 联接表查询的细节,在这里记录以便查询. 一.交叉联接 交叉联接仅执行一个罗辑查询处理阶段——笛卡尔积.也就是说,将一个输入表的每一行与另一个表的所有行匹配. ...
- Solr 单机配置
一. 准备软件 提前安装好Java1.8和Tomcat9 下载Solr6.1,官网位置:http://mirrors.tuna.tsinghua.edu.cn/apache/lucene/solr/6 ...
- 转:VC中UpdateData()函数的使用
VC中UpdateData()函数的使用 UpdateData(FALSE)与UpdateData(TRUE)是相反的过程 UpdateData(FALSE)是把程序中改变的值更新到控件中去 ...
- uva 10026 Shoemaker's Problem
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- mysql连接的空闲时间超过8小时后 MySQL自动断开该连接解决方案
在连接字符串中 添加设置节点 ConnectionLifeTime(计量单位为 秒).超过设定的连接会话 会被杀死! Connection Lifetime, ConnectionLifeTime ...
- oracle11g rac asm 实例内存修改
ASM实例内存修改 memory_max_target(它为静态参数,修改完成后需要重启实例) memory_target(它为动态参数,不需要重启实例) SQL> select name,is ...
- 硝烟中的Scrum和XP-我们如何实施Scrum 4 (Part 1/2)
4 制定Sprint计划 计划是Scrum中重要的一环; 是为了让团队获得足够信息, 不受打扰地工作, 增加团队的信心; Planning的成果: 1) Sprint目标 2) 团队成员名单(时间百分 ...
- Linux系统编程(36)—— socket编程之UDP详解
UDP 是User DatagramProtocol的简称,中文名是用户数据报协议.UDP协议不面向连接,也不保证传输的可靠性,例如: 1.发送端的UDP协议层只管把应用层传来的数据封装成段交给IP协 ...