一、事件流

事件流,描述的是页面中接受事件的顺序,不过,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. JavaScript的词法作用域问题

    多年以前,当我怀揣着前端工程师的梦想时,曾经认真阅读过<JavaScript高级程序设计(第2版)>.里面有一个问题(P147),让我一直百思不得其解. function createFu ...

  2. Java 实现 WC.exe

    Github:https://github.com/YJOED/Code/tree/master/WC/src 一.题目:实现一个统计程序,它能正确统计程序文件中的字符数.单词数.行数,以及还具备其他 ...

  3. nginx uwsgi flask相关配置

    一.安装Nginx 在 /home/download下下载压缩包 wget https://nginx.org/download/nginx-1.12.2.tar.gz 解压缩 tar zxvf ng ...

  4. OI图论 简单学习笔记

    网络流另开了一个专题,所以在这里就不详细叙述了. 图 一般表示为\(G=(V,E)\),V表示点集,E表示边集 定义图G为简单图,当且仅当图G没有重边和自环. 对于图G=(V,E)和图G2=(V2,E ...

  5. WebStrom创建自定义后缀名的文件

    如下图所示,我在下面的项目里面创建了.ejs文件,但是正常的情况下我们WebStrom是无法创建.ejs文件的,那么我们怎么才能让我们的WebStrom拥有创建该后缀名的文件的能力呢? 不BB,直接看 ...

  6. 十九、Node.js-非阻塞IO、异步以及 '事件驱动EventEmitter'解决异步

    1.Nodejs 的单线程 非阻塞 I/O 事件驱动 在 Java.PHP 或者.net 等服务器端语言中,会为每一个客户端连接创建一个新的线程而每个线程需要耗费大约 2MB 内存.也就是说,理论上, ...

  7. 多线程DP

    Matrix Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  8. javascript显示年月日时间代码显示电脑时间

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. Easyui里面动态设置输入框的可见性

    JQuery EasyUI 动态隐藏   一.隐藏datagrid某一列 $('#dg').datagrid('hideColumn', 'field'); 二.隐藏html的lable.input标 ...

  10. Python处理json数据--世界国家维度数据

    1.准备国家的json数据 将准备好的json数据放在指定的目录下,此处可以重这里下载 2.测试编写python脚本处理json提取字段值 #coding:utf8 import time, re, ...