《JS高程》事件学习笔记

事件:文档或浏览器窗口中发生的一些特定的交互瞬间,也即用户或浏览器自身执行的某种动作。

-------------------------------------------------------------------------------------------------------------

一、事件流

事件流:描述的是页面中接收事件的顺序。

IE:事件冒泡流,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点(文档);

NetScape:事件捕获流,即不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。其用意在于在事件达到预定目标之前捕获它。

DOM事件流:


(1)事件捕获阶段:建立了传播路径,为截获事件提供了机会

(2)处于目标阶段:目标接收到事件,并触发;

(3)事件冒泡阶段:在这个阶段对事件做出响应,事件会通过这个路径回溯到文档根节点。

在 DOM 事件流中,实际的目标(div元素)在捕获阶段不会接收到事件。

-->这意味着在捕获阶段,事件从 document 到 <html> 再到 <body> 后就停止了。

-->下一阶段是“处于目标”阶段,于是事件在 <div> 上发生,并在事件处理中被看成冒泡阶段的一部分。

-->然后,冒泡阶段发生,事件又传播回文档。

*多数支持 DOM 事件流的浏览器都实现了一种特定的行为;即使“DOM2级事件“规范明确要求捕获阶段不会涉及事件目标,但各种浏览器的高版本都会在不惑阶段触发事件对象上的事件。结果,就是有两个机会在目标对象上面操作事件。

-------------------------------------------------------------------------------------------------------------

二、事件处理程序

事件处理程序(事件侦听器):响应某个事件的函数。

事件处理程序的名字以 "on" 开头。如 click、load(事件)—> onclick、onload(事件处理程序)

1. HTML 事件处理程序

——this 值等于事件的目标元素

使用与相应事件处理程序同名的 HTML 特性来指定

<input type="button" value="Click me" onclick="alert(event.type)">

优点
(1)有权访问全局作用域中的任何代码;

(2)会封装着元素属性值的函数,这个函数中有局部变量 event,即事件对象;
(3)在这个函数内部,this 值等于事件的目标元素;
(4)扩展作用域。在这个函数内部,可以像访问局部变量一样访问 document 及该元素本身的成员;可以让事件处理程序无需引用表单元素就能访问其他表单字段。


缺点

(1)存在时差问题;

(2)这样扩展事件处理程序的作用域链在不同浏览器中会导致不同结果;

(3)HTML 与 JavaScript 代码紧密耦合。


删除事件处理程序  

将相应的属性设置为 nul

2. DOM0 级事件处理程序

——元素的方法(事件处理程序在元素的作用域中运行,this 引用当前元素)


方法

(1)首先,必须取得一个要操作的对象的引用;

(2)将一个函数赋值给一个事件处理程序属性


缺点

对每个事件只支持一个事件处理程序

删除事件处理程序

将事件处理程序属性设置为 null

事件处理阶段

在事件流的冒泡阶段被处理

每个元素(包括 window 和 document)都有自己的事件处理程序属性(通常全部小写,如 onclick)。

var btn = document.getElementById("myBtn");
btn.onclick = function() {
    alert(this.id);    // "myBtn"
};
btn.onclick = null;    // 删除事件处理程序

3. DOM2 级事件处理程序

——在其依附的元素的作用域中运行


方法

(1)指定事件处理程序:addEventListener()

(2)删除事件处理程序:removeEventListener()


方法的参数

要处理的事件名

作为事件处理程序的函数

布尔值(true 表示捕获阶段调用事件处理程序,false 表示冒泡阶段调用事件处理程序)


好处

可以添加多个事件处理程序
移除事件处理程序
只能通过 removeEventListener() 来移除;

移除时传入的参数与添加处理程序时使用的参数相同,使用匿名函数无法移除。


事件处理阶段

大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段;

如果不是特别需要,不建议在事件捕获阶段注册事件处理程序。

var btn = document.getElementById("myBtn");
var handler = function() {
    alert(this.id);
};
btn.addEventListener("click", handler, false);
btn.removeEventListener("click", handler, false);    // 删除事件处理程序

4. IE 事件处理程序

方法
(1)attachEvent()

(2)detachEvent()


方法的参数

事件处理程序名称、事件处理程序函数

好处

可以添加多个事件处理程序,同 addEventListener()

移除事件处理程序

通过 detachEvent() 来移除,必须提供相同的参数,同 DOM 方法

与 DOM0 级方法区别

主要区别在于事件处理程序的作用域:

DOM0 级方法:事件处理程序会在其所属元素的作用域内运行;

attachEvent() 方法:事件处理程序会在全局作用域中运行,因此 this 等于 window。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function() {
    alert(this === window);    // true
});

5. 跨浏览器的事件处理程序


对象

EventUtil(用于处理浏览器间的差异)
方法
addHandler():视情况分别使用 DOM0 级方法、DOM2 级方法或 IE 方法来添加事件

removeHandler():移除添加的事件处理程序

参数
要操作的元素、事件名称、事件处理程序函数
缺点
没有考虑到所有的浏览器问题,例如在 IE 中的作用域问题。

不过,使用它们添加和移除事件处理程序还是足够了。

 1 // 定义EventUtil对象
 2 var EventUtil = {
 3
 4     addHandler: function(element, type, handler) {
 5         if (element.addEventListener) {
 6             element.addEventListener(type, handler, false);
 7         } else if (element.attachEvent) {
 8             element.attachEvent("on" + type, handler);
 9         } else {
10             element["on" + type] = handler;
11         }
12     },
13     removeHandler: function(element, type, handler) {
14         if (element.removeEventListener) {
15             element.removeEventListener(type, handler, false);
16         } else if (element.detachEvent) {
17             element.detachEvent("on" + type, handler);
18         } else {
19             element["on" + type] = null;
20         }
21     }
22 }
23
24 // 使用EventUtil对象
25 var btn = document.getElementById("myBtn");
26 var handler = function() {
27     alert("Clicked");
28 }
29
30 EventUtil.addHandler(btn, "click", handler);
31 EventUtil.removeHandler(btn, "click", handler);

EventUtil对象方法定义及用法

-------------------------------------------------------------------------------------------------------------

三、事件对象

事件对象:在触发DOM上的某个事件时,会产生一个事件对象 event,这个对象中包含着所有与事件有关的信息。包括导致事件的元素、事件的类型及其他与特定事件相关的信息。

(1)DOM 中的事件对象

 兼容 DOM 的浏览器会将一个 event 对象传入到事件处理程序中。无论指定事件处理程序时使用什么方法(DOM0 级或 DOM2 级),都会传入 event 对象。

var btn = document.getElementById("myBtn");
btn.onclick = function(event) {
  alert(event.type);      // "click"
}
btn.addEventListener("click", function(event){
  alert(event.type);    // "click"
}, false);

 在通过 HTML 特性指定事件处理程序时,变量 event 中保存着 event 对象。

<input type="button" value="Click Me" onclick="alert(event.type)" />

 event 对象包含与创建它的特定事件相关的属性和方法。触发的事件类型不一样,可用的属性和方法也不一样。不过,所有事件都会有下表列出的成员。


属性/方法

类型

读/写  

说明

bubbles                                

Boolean         

只读   

表明事件是否冒泡

cancelable

Boolean

只读

表明是否可以取消事件的默认行为

currentTarget

Element

只读

其事件处理程序当前正在处理事件的那个元素

defaultPrevented

Boolean

只读

为 true 表示已经调用了 preventDefault() (DOM3 级事件中新增)

detail

Integer

只读

与事件相关的细节信息

eventPhase

Integer

只读

调用事件处理程序的阶段:1 表示捕获阶段,2 表示“处于目标,3 表示冒泡阶段

preventDefault()

Function
只读
取消事件的默认行为。如果 cancelable 是 true,则可以使用该方法

stopImmediatePropagation()

Function

只读

取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用(DOM3 级事件中新增)

stopPropagation()

Function

只读

取消事件的进一步捕获或冒泡。如果 bubbles 为 true,则可以使用该方法

target

Element

只读

事件的目标

trusted

Boolean

只读

为 true 表示事件是浏览器生成的。为 false 表示事件由开发人员通过 JavaScript 创建的(DOM3 级事件中新增)

type

String

只读

被触发的事件的类型,需要通过一个函数处理多个事件时使用

view

AbstractView

只读

与事件关联的抽象视图。等同于发生事件的 window 对象

 在事件处理程序内部,对象 this 始终等于 currentTarget 的值,而 target 则只包含事件的实际目标。如果直接将事件处理程序指定给了目标元素,则 this、currentTarget 和 target 包含相同的值。

 尽管 "处于目标" 发生在冒泡阶段,但 eventPhase 仍然一直等于 2 。

 只有在事件处理程序执行期间,event 对象才会存在;一旦事件处理程序执行完成,event 对象就会被销毁。

(2)IE 中的事件对象

与访问 DOM 中的 event 对象不同,要访问 IE 中的 event 对象有几种不同的方式,取决于指定事件处理程序的方法。

—>在使用 DOM0 级方法添加事件处理程序时,event 对象作为 window 对象的一个属性存在(window.event)。

btn.onclick = function() {
    var event = window.event;
    alert(event.type);    // "click"
};

—>如果事件处理程序是使用 attachEvent() 添加的,event 对象会作为参数被传入事件处理程序中。也可通过 window 对象来访问 event 对象,同 DOM0 级方法。

btn.attachEvent("onclick", function(event) {
    alert(event.type);    // "click"
});

—>如果是通过 HTML 特性指定的事件处理程序,可以通过一个名叫 event 的变量来访问 event 对象。

<input type="button" onclick="alert(event.type)" >

IE 的所有 event 对象都包含的属性和方法:


属性/方法

类型

读/写

说明

cancleBubble

Boolean

读/写

默认值为 false,但将其设置为 true 就可以取消事件冒泡

(同 DOM 中的 stopPropagation() 方法)


returnValue

Boolean

读/写

默认值为 true,但将其设置为 false 就可以取消事件的默认行为

(同 DOM 中的 preventDefault() 方法)


srcElement

Element

只读

事件的目标(同 DOM 中的 target 属性)

type

String

只读

被触发的事件的类型

因为事件处理程序的作用域是根据指定它的方式来确定的,所以不能认为 this 会始终等于事件目标。故而,最好还是使用 event.srcElement 比较保险

(3)跨浏览器的事件对象


对象

EventUtil(用于处理浏览器间的差异)
方法 getEvent():返回对 event 对象的引用
getTarget():返回事件的目标
preventDefault():用于取消事件的默认行为
stopPropagation():阻止事件流

 1 // 定义EventUtil对象
 2 var EventUtil = {
 3
 4     addHandler: function(element, type, handler) {
 5         if (element.addEventListener) {
 6             element.addEventListener(type, handler, false);
 7         } else if (element.attachEvent) {
 8             element.attachEvent("on" + type, handler);
 9         } else {
10             element["on" + type] = handler;
11         }
12     },
13
14     getEvent: function(event) {
15         return event ? event : window.event;
16     },
17
18     getTarget: function(event) {
19         return event.targete || event.srcElement;
20     },
21
22     preventDefault: function(event) {
23         if (event.preventDefault) {
24             event.preventDefault();
25         } else {
26             event.retrunValue = false;
27         }
28     },
29
30     removeHandler: function(element, type, handler) {
31         if (element.removeEventListener) {
32             element.removeEventListener(type, handler, false);
33         } else if (element.detachEvent) {
34             element.detachEvent("on" + type, handler);
35         } else {
36             element["on" + type] = null;
37         }
38     },
39
40     stopPropagation: function(event) {
41         if (event.stopPropagation) {
42             event.stopPropagation();
43         } else {
44             event.cancleBubble = true;
45         }
46     }
47 }
48
49 // 使用EventUtil对象
50 var btn = document.getElementById("myBtn");
51 var handler = function() {
52     alert("Clicked");
53 }
54
55 EventUtil.addHandler(btn, "click", handler);
56
57 btn.onclick = function(event) {
58     event.EventUtil.getEvent(event);
59     var target = EventUtil.getTarget(event);
60     EventUtil.preventDefault(event);
61     EventUtil.stopPropagation(event);
62 }
63
64 EventUtil.removeHandler(btn, "click", handler);

EventUtil对象方法定义及用法

-------------------------------------------------------------------------------------------------------------

四、事件类型

 《JS高程事件类型学习笔记》

-------------------------------------------------------------------------------------------------------------

五、内存和性能

添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能。

原因:(1)每个函数都是对象,都会占用内存;内存中的对象越多,性能就越差;

(2)必须事先指定所有事件处理程序而导致的 DOM 访问次数,会延迟整个页面的交互就绪时间。

解决方案:

(1)事件委托:利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件

使用事件委托,只需在 DOM 树中尽量最高的层次上添加一个事件处理程序。

所有用到按钮的事件(多数鼠标事件和键盘事件)都适合采用事件委托技术。最适合的事件包括 click、mousedown、mouseup、keydown、keyup 和 keypress,mouseover 和 mouseout 不适合,因为处理不容易。

如果可行的话,也可以考虑为 document 对象添加一个事件处理程序,用以处理页面上发生的某种特定类型的事件。

(2)移除事件处理程序:在事件处理程序中删除按钮也能阻止事件冒泡

参考博文:

深入浅出js事件

游览器中有哪些事件会冒泡?

解析JavaScript事件冒泡机制

时间: 2024-12-21 08:42:44

《JS高程》事件学习笔记的相关文章

JS 事件学习笔记(二)

在JS事件学习笔记(一)中学习了事件流.事件处理程序.事件对象以及跨浏览器应该怎么做等知识,现在我们现在来学习浏览器中主要的各种事件. 一. load事件 load事件通常是通过JavaScript代码指定,在window对象上绑定,实际上根据DOM2规定,应该在document上而非window上触发load事件,但是所有浏览器都在window对象上实现了该事件.因此以确保兼容性推荐使用该方法: 另外,在window上发生的事件也可以作为body元素的属性在html代码中添加. load事件的

node.js框架StrongLoop学习笔记(一)

node.js框架StrongLoop学习笔记(一) 本人在用node.js做手机后台,查找框架发现StrongLoop挺适合,可是却发现没有中文教程,于是在自己学习时,做一下笔记,以方便其他像我一样的人参考(本人的英语水平非常差,只能一点点试着做,并记录下来,如果大家发现问题,请通知我好更正,谢谢了!).所有操作都是在CentOS7-x64,Node.js 0.12.2下完成的. nodejs框架StrongLoop学习笔记一 安装StrongLoop 创建项目 安装数据库驱动 配置数据库连接

C#中的委托、事件学习笔记

1.委托delegate 委托delegate也是一种类型,在任何可以声明类的地方都可以声明委托,它将方法当做另一个方法的参数进行传递,这样就可以传递不同的方法,完成不同的功能,使程序具有很好的可扩展性. 举例: 假设这里有一台电脑,有人会用它写程序,有人会用它打游戏,有人会用它看电影,有人会用它边听音乐边玩游戏,有人会用它边听音乐边看文档,边上QQ. 这台电脑可以抽象成一个类Computer,里面有个方法DoWork,所有的人都要通过这个方法来做自己的事情. 不用委托的时候我们可以实现一些固定

JS高级程序设计学习笔记之JS事件(1)

事件流 冒泡 定义:事件开始时由最具体的元素接收,然后逐级上传到较为不具体的节点.(IE9.FF.Chrome.Safari会将事件一直冒泡到window对象.IE5.5及其以下会跳过<html>元素,直接从body跳到document).若发生事件的节点元素并没有绑定该事件,则这个动作会向上冒泡,直到被执行,一直冒泡到window对象. 阻止冒泡:①使用stoppropagation() ②在函数中进行一次判断,if(event.target==event.current.target){f

js的dom学习笔记一

前言: 我现在不好定位自己程序编写的技术的好坏,新手吧.DOM是实现js脚本连接上HTML文档的一个API,才接触jquery一两天,大概能明白,所谓的框架,就是在原生态的基础上做出的函数库,里面的方法.属性都是要使用该框架的对象来调用的.相比于jquery,DOM不是框架,虽然它们都能实现操控网页文档元素,DOM更加底层,dom的方法.属性直接面对文档元素来使用,而jquery要面向jquery对象来使用. DOM 是一个可以让javaScript脚本操控HTML元素.css属性的一套w3c标

JS与Jquery学习笔记(二)

施工中........... 一. JS 的面向对象 二. 用JS移动和复制元素 三. 如何给动态生成的元素绑定事件 四. 事件绑定函数的入参 五. $.each和$.map的用法与区别

js基础教程学习笔记

document.write(); document.getElementById(); <script type="text/javascript"></script> 表示在<script></script>之间的文本类型text,javascript是为了告诉浏览器里面的文本是javascript语言 我们可以把js代码与html代码分开,并在html中引用: <script src="script.js"

C#委托与事件学习笔记

今天跟随视频学习了一下C#中最重要的一些概念之委托与事件.老杨的视频讲的还是挺深入浅出,不过刚接触C#.NET的人还是朦朦胧胧,就像张子阳先生说的"每次见到委托和事件就觉得心里别(biè)得慌,混身不自在".跨过这道坎的人就有种一览众山小的感觉了.我又浏览了皱华栋老师JamesZou的博文<深入理解C#委托及原理>(地址:http://www.cnblogs.com/jameszou/archive/2011/07/21/2112497.html),以及张子阳Jimmy Z

jquery事件学习笔记(转载)

一.页面载入1.ready(fn)当DOM载入就绪可以查询及操纵时绑定一个要执行的函数.这是事件模块中最重要的一个函数,因为它可以极大地提高web应用程序的响应速度. 简单地说,这个方法纯粹是对向window.load事件注册事件的替代方法.通过使用这个方法,可以在DOM载入就绪能够读取并操纵时立即调用你所绑定的函数,而99.99%的JavaScript函数都需要在那一刻执行.有一个参数--对jQuery函数的引用--会传递到这个ready事件处理函数中.可以给这个参数任意起一个名字,并因此可以