一、事件流

事件流,描述的是页面中接受事件的顺序,不过,IE的事件流是事件冒泡流,而Netscape Communicator的事件流是事件捕获型。标准同时支持两种事件模型,即捕获型事件与冒泡型事件,但是,捕获型事件先发生。

两种事件流都会触发DOM中的所有对象,从document对象开始,也在document对象结束(大部分兼容标准的浏览器会继续将事件是捕捉/冒泡延续到window对象)JavaScript与HTML之间的交,通过事件实现。常用观察员模式,使用侦听器来预定事件,以便事件发生时执行相应的代码。

DOM(文档对象模型)结构是一个树型结构,当一个HTML元素产生一个事件时,该事件会在元素结点与根节点之间按特定的顺序传播,路径所经过的节点都会收到该事件,这个传播过程可称为DOM事件流。

二、事件句柄和事件监听器

事件句柄与事件监听器的最大不同之处是使用事件句柄时一次只能插接一个事件句柄,但对于事件监听器,一次可以插接多个。现在大多数浏览器都内置了一些更高级的事件处理方式,即,事件监听器,这种处理方式就不受一个元素只能绑定一个事件句柄的限制。

获取事件的目标

HTML如下:

body id="myBody">
<button id="myButton">click</button>
</body>

1. IE下的事件监听器:attachEvent接受两个参数。第一个参数是事件类型名,第二个参数eventListener是回调处理函数。

在IE中,每个元素和window对象都有两个方法:attachEvent方法和detachEvent方法。

IE 事件对象使用 event 的 srcElement 属性获取事件目标。

var btn = document.getElementById("myButton");
btn.attachEvent("onclick", function(event) {
alert(event.srcElement.id); // myButton
});

2. DOM标准下的事件监听器:addEventListener

addEventListener方法接受三个参数。第一个参数是事件类型名,值得注意的是,这里事件类型名称与IE的不同,事件类型名是没’on’开头的;第二个参数eventListener是回调处理函数(即监听器函数);第三个参数注明该处理回调函数是在事件传递过程中的捕获阶段被调用还是冒泡阶段被调用 ,通常此参数通常会设置为false(为false时是冒泡),如果将其值设置为true,那就创建一个捕捉事件监听器。

通过addEventListener方法添加的事件处理函数,必须使用removeEventListener方法才能删除,而且要求参数与添加事件处理函数时addEventListener方法的参数完全一致(包括useCapture参数),否则将不能成功删除事件处理函数。

标准事件对象使用 event 的 target 属性获取事件目标:


var btn = document.getElementById('myButton');
btn.addEventListener("click", function(event) {
alert(event.target.id); // myButton
});

三、取消事件默认行为

html结构如下:

<div id="oDiv">
<a id="oA" href="http://baidu.com">
百度一下,你就知道。
</a>
</div>

正常情况下,我们点击a链接,会跳转到baidu.com,但当使用了e.preventDefault().

JS代码如下:

var a = document.getElementById("oA");

    //获取div
var oDiv = document.getElementById('oDiv'); //dom0级绑定事件方法
a.onclick=function(e){
e.preventDefault();
}
// 旧版本IE不支持捕获,一般使用冒泡。
oDiv.addEventListener("click", function (e) {
e.preventDefault();
}, false);

四、禁止冒泡

一、正常情况下:

//关于阻止事件冒泡.ie678用attachEvent
a.addEventListener("click", function (e) {
alert(1);
}, false);//冒泡 oDiv.addEventListener("click", function (e) {
alert(2)
}, false);//冒泡 oDiv.addEventListener("click", function (e) {
alert(3);
}, true);//捕获,捕获先发生

第3个参数设置为false时候为冒泡,先捕获,后冒泡。这里弹出顺序依次是:3,1,2

二、禁止冒泡时:用到stopPropagation

    //关于阻止事件冒泡.ie678用attachEvent
a.addEventListener("click", function (e) {
e.stopPropagation();//阻止冒泡/捕获
alert(1);
}, false);//冒泡 oDiv.addEventListener("click", function (e) {
alert(2)
}, false);//冒泡 oDiv.addEventListener("click", function (e) {
e.stopPropagation();
alert(3);
}, true);//捕获,捕获先发生

这时候顺序是:3,不会出现1,2。因为在第3个函数里用到了stopPropagation,而且捕获比冒泡事件先发生。所以只会出现3.

注意:e.cancelBubble = true对应取消冒泡;e.returnValue = true对应阻止默认行为

五、addEventListener与attachEvent区别

1. 支持的浏览器

    addEventListener在支持DOM2的浏览器中使用,如FF, Chrome等

    attachEvent为IE所用

2. 处理程序执行阶段

    addEventListener的第三个参数为true时,在捕获阶段执行,为false时,在冒泡阶段执行

    attachEvent的均在冒泡阶段执行

3. 作用域

    addEventListener的作用域为元素作用域,this为element的引用

    addEvent的为全局作用域,this为window的引用

4. 事件处理程序执行顺序

    addEventHander:执行顺序与添加顺序一致

    attachEvent:执行顺序与添加顺序相反

5. 针对的事件不同

    attachEvent中的事件带on 

    addEventListener中的事件不带on

六、冒泡的用处

例如:有一个10列、100行的HTML表格,假如有一次你需要让表格中的每一个单元格在被点击的时候变成可编辑状态。

如果把事件处理器加到这1000个单元格会产生一个很大的性能问题,并且有可能导致内存泄露甚至是浏览器的崩溃。

相反地,使用事件代理的话,只需要把一个事件处理器添加到table元素上就可以了,这个函数可以把点击事件给截下来,并且判断出是哪个单元格被点击了。

比如:有一个 table元素,ID是“report”,我们为这个表格添加一个事件处理器以调用editCell函数。editCell函数需要判断出传到table 来的事件的目标元素。考虑到我们要写的几个函数中都有可能用到这一功能,所以我们把它单独放到一个名为getEventTarget的函数中:


function getEventTarget(e) {
e = e || window.event;
return e.target || e.srcElement;
}

e这个变量表示的是一个事件对象,我们只需要写一点点跨浏览器的代码来返回目标元素,在IE里目标元素放在srcElemtn属性或event.toElement属性中,而在其它浏览器里则是target或event.relatedTarget属性。

接下来就是editCell函数了,这个函数调用到了 getEventTarget函数。一旦我们得到了目标元素之后,剩下的事情就是看看它是否是我们所需要的那个元素了。

function editCell(e) {
var target = getEventTarget(e);
if(target.tagName.toLowerCase() === 'td') {
// DO SOMETHING WITH THE CELL
}
}

通过事件冒泡,那些需要创建的以及驻留在内存中的事件处理器少了。这样我们就提高了性能,并降低了崩溃的风险。

参考:《JavaScript高级程序设计》

JavaScirpt事件处理的更多相关文章

  1. JavaScript权威设计--事件处理介绍(简要学习笔记十七)

    1.事件相关概念 事件类型:一个用来说明发生什么类型事件的字符串 事件目标:是发生的事件或与之相关的对象. 事件处理程序(事件监听程序):是处理货响应事件的函数. 事件对象:是与特定事件相关并且包含有 ...

  2. JavaScript移除绑定在元素上的匿名事件处理函数

    前言: 面试的时候有点蒙,结束之后想想自己好像根本就误解了面试官的问题,因为我理解的这个问题本身就没有意义.但是当时已经有一些思路,但是在一个点上被卡住. 结束之后脑子瞬间灵光,想出了当时没有迈出的那 ...

  3. linux输入子系统(input subsystem)之evdev.c事件处理过程

    1.代码 input_subsys.drv.c 在linux输入子系统(input subsystem)之按键输入和LED控制的基础上有小改动,input_subsys_test.c不变. input ...

  4. 【repost】JavaScript 事件模型 事件处理机制

    什么是事件? 事件(Event)是JavaScript应用跳动的心脏 ,也是把所有东西粘在一起的胶水.当我们与浏览器中 Web 页面进行某些类型的交互时,事件就发生了.事件可能是用户在某些内容上的点击 ...

  5. 【原】iOS学习之事件处理的原理

    在iOS学习23之事件处理中,小编详细的介绍了事件处理,在这里小编叙述一下它的相关原理 1.UITouch对象 在触摸事件的处理方法中都会有一个存放着UITouch对象的集合,这个参数有什么用呢? ( ...

  6. android事件处理之基于监听

    Android提供了了两种事件处理方式:基于回调和基于监听. 基于监听: 监听涉及事件源,事件,事件监听器.用注册监听器的方法将某个监听器注册到事件源上,就可以对发生在事件源上的时间进行监听. 最简单 ...

  7. Nova PhoneGap框架 第七章 设备事件处理

    我们的框架包含了几种设备事件的处理,目的是为了让我们的程序员更容易的完成代码.这些事件包括:回退键(Android)和横竖屏切换事件. 7.1 Android回退键 首先来说说回退键的事件处理.当用户 ...

  8. 译:DOM2中的高级事件处理(转)

    17.2. DOM2中的高级事件处理(Advanced Event Handling with DOM Level 2)        译自:JavaScript: The Definitive Gu ...

  9. Java基础学习 -- GUI之 事件处理基础

    事件处理可以简单地这么理解,当有一个事件产生,程序要根据这个事件做出响应.比如,我们做了一个可以通过按钮改变背景颜色的窗口,当我们点击按钮时便产生了一个事件,程序会根据这个事件来做出响应,也就是去改变 ...

随机推荐

  1. duilib入门简明教程 -- XML配置界面(6)

       前面那些教程都是为了让小伙伴们从win32.MFC过渡到duilib,让大家觉得duilib不是那么陌生,如果大家现在还对duilib非常陌生的话,那就说明前面的教程做得不好,请大家在下面留言, ...

  2. 神器与经典--sp_helpIndex

    ======================================================= 每每和那些NB的人学习技术的时候,往往都佩服他们对各个知识点都熟捻于心,更佩服的是可以在 ...

  3. Spring学习(一)——环境准备

            以前做的项目都是用.net开发的,以后准备迁移到java平台上,近期正好有个新项目要上马,所以调研下java相关技术.Spring作为java平台下的一个全栈框架, 其简洁优雅的设计和 ...

  4. HBase介绍(4)---常用shell命令

    进入hbase shell console$HBASE_HOME/bin/hbase shell如果有kerberos认证,需要事先使用相应的keytab进行一下认证(使用kinit命令),认证成功之 ...

  5. 691. Stickers to Spell Word

    We are given N different types of stickers. Each sticker has a lowercase English word on it. You wou ...

  6. [AIR] AIR将数据保存并导出为Excel

    package { import flash.display.Sprite; import flash.events.MouseEvent; import flash.filesystem.File; ...

  7. Spark JavaRDD、JavaPairRDD、Dataset相互转换与打印

    主要内容: 1. List转JavaRDD,打印JavaRDD 2. List转JavaRDD,JavaRDD转JavaPairRDD,打印JavaPairRDD 3. JavaRDD<Stri ...

  8. django中@property装饰器的运用

    python提供的内置装饰器——staticmethod.classmethod和property 在OSQA中,@property的使用频率是非常高的.下面就是它的使用方法: @property 可 ...

  9. P4491 [HAOI2018]染色 容斥+NTT

    $ \color{#0066ff}{ 题目描述 }$ 为了报答小 C 的苹果, 小 G 打算送给热爱美术的小 C 一块画布, 这块画布可 以抽象为一个长度为 \(N\) 的序列, 每个位置都可以被染成 ...

  10. CSS3 文本溢出问题

    一.单行: 效果: 实现这各效果必须要加上: text-overflow: ellipsis; /*文本溢出*/ overflow: hidden; /*配合使用:溢出隐藏*/ white-space ...