事件读书笔记

  • cindy Liu
  • 19 Minutes
  • January 29, 2019

事件

本章内容 (p363-p429)

DOM2级事件规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段

DOM0级事件处理程序
1
2
3
4
5
6
7
8
var btn = document.getElementById("myBtn")
btn.onclick = function(){
alert("click");
}


// 删除事件处理程序
btn.onclick = null
DOM2级事件处理程序

定义了两个方法,用于处理制定和删除事件程序的操作:addEventListener() 和 removeEventListener()。所有DOM节点都包含这两个方法,并且都接受3个参数:

使用DOM2级方法的除妖好处是可以添加多个事件处理程序,多个程序会按添加顺序触发

1
2
3
4
5
6
7
8
9
var btn = document.getElementById("myBtn");

btn.addEventListener("click",function(){
alert(this.id;)
},false)

btn.addEventListener("click",function(){
alert("Hello world");
},false)

通过addEventListener()添加的事件只能通过removeEventLisener() 来移除,移除时传入的参数与添加时候的参数相同,以为着通过addEventListener()添加的匿名函数将无法移除。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//以下移除方法removeEventLisener()无效,因为第二个参数是一个完全不同的函数
var btn = document.getElemetnById("myBtn")
btn.addEventListener("click",function(){
alert(this.id;)
},false)
btn.removeEventListener("click",function(){
alert(this.id;)
},false)


//以下移除方法有效
var btn = document.getElemetnById("myBtn")
btn.addEventListener("click",hendler,false)
btn.removeEventListener("click",hendler,false)

如果不是特别需要,我们不建议在事件捕获阶段注册事件处理程序。大多数情况下都是在冒泡阶段,可以最大限度地兼容各种浏览器

IE事件处理程序

….

跨浏览器的事件处理程序

要保证处理事件的代码在大多数浏览器下一致地运行,只需关注冒泡阶段。
(以下代码最好记下来)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
var EventUtil = {
addHandler: funciton(element, type, handler){
if(element.addEventListener){
element.addEventListener(type, handler, false)
}else if(element.attachEvent){
element.attachEvent('on'+type, handler)
}else {
element['on'+type] = handler;
}
}

removeHandler: function(element, type ,handler){
if(element.removeEventListener){
element.removeEventListener(type, handler, false)
}else if(element.datachEvent){
element.datachEvent('on'+type, handler)
}else {
element['on'+type] = null
}
}
};



//以下是调用方式
var btn = document.getElementById("myBtn")
var handler = function(){
alert("Cliked")
};
EventUtil.addHandler(btn, "click", handler)
//这里省略了其他代码
EventUtil.removeHandler(btn, "click", handler)

事件对象event

触发DOM上的某个事件时,会产生一个事件对象event,包含与事件有关的信息。
常用的属性方法:
属性/方法 | 说明
—|—
currentTarget | 其事件处理程序当前正在处理事件的那个元素
target | 事件的目标
preventDefault() | 取消事件的默认行为
stopPropagation() | 取消事件的进一步捕获或冒泡,同时组织任何事件处理程序被调用

currentTarget 和 target 的区别

在事件处理程序内部,this始终等于currentTartget的值,而target则只包含事件的实际目标。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 如果直接将事件处理程序制定给了缪奥元素,则this、currentTarget和terget包含相同的值
var btn = document.getElementById("myBtn")
btn.onclick = function(event){
alert(event.currentTarget === this) //ture
alert(evnet.target === this ) // ture
}

//如果事件处理程序存于父结点中,那么这些值是不同的
document.body.onclick = function(event){
alert(event.currentTarget === document.body ) //ture
alert(document.body === this ) //ture
alert(event.target === document.getElementById("myBtn")) // ture
}
preventDefault() 取消默认行为
1
2
3
4
var link = document.getElementById("myLink")
link.onclick = function(event){
event.preventDefault();
}
stopPropagation() 立即停止事件在DOM层次中的传播,取消进一步的事件捕获或冒泡
1
2
3
4
5
6
7
8
9
var btn = document.getElementById("myBtn")
btn.onclick = function(event){
alert("clicked")
event.stopPropagation
}

document.body.onclick = function(event){
alert("body clicked")
}
eventPhase 属性 判断事件处于哪个阶段

事件类型

load 图片懒加载

懒加载和预加载

事件委托

对“事件处理程序过多”的解决方案就是事件委托。事件委托利用了事件冒泡,制定一个事件处理程序,就可以管理某一类型的所有事件。

1
2
3
4
5
6
// html
<ul id = "myLinks">
<li id="goSomewhere"> Go Somewhere</li>
<li id="doSomething"> Do Something</li>
<li id="sayHi"> Say Hi</li>
</ul>

按照传统的方法,要为他们添加3个事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var item1 = document.getElementById("goSomewhere")
var item2 = document.getElementById("doSomething")
var item3 = document.getElementById("sayHi")

EventUtil.addHandler(item1,"click",function(event){
location.href = 'http://www.wrox.com'
})

EventUtil.addHandler(item2,"click",function(event){
document.title = "I changed the document's title "

EventUtil.addHandler(item3,"click",function(event){
alert("hi")
})

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var list = document.getElementById("myLinks")

EventUtil.addHandler(list,'click',function(event){
event = EventUtil.getEvent(event)
var target = EventUtil.getTarget(event)

switch(target.id){
case "doSomething":
document.title = "I changed the document's title "
break;

case "goSomewhere":
location.href = 'http://www.wrox.com'
break;

case "sayHi":
alert("hi")
break;
}
})

事件委托的优点是需要占用的内存更少,对DOM的操作更少。