DOM事件。事件的定义,就是文档和浏览器窗口发生的一些特定交互的瞬间。此文出自JavaScript高级程序设计一书对事件的定义
事件流
事件冒泡
事件冒泡是IE事件流,当点击一个按钮时是由内而外,就是事件点击焦点逐级向上
1
2
3
4
5
6
7
8
9
10
|
<html>
<head>
<title>test
</title>
</head>
<body>
<div id="app">
</div>
</body>
</html>
|
点击id为app事件顺序为,div body html document
事件捕获
事件捕获的顺序侧相反。
DOM事件流
DOM2级事件流包括三个阶段:事件捕获、目标阶段、冒泡阶段。顺序为
document html body | div body html document.
DOM2级事件明确规定捕获阶段不涉及目标元素
以上就是DOM具有的事件流的简单介绍,让我们有一个初步的认识。有了事件,我们就应该有相应的动作,而这个动作就是官方说的事件处理程序
事件处理程序
事件处理程序一on开头,就是我们常常看到的onclick,onload等。
DOM0级事件处理程序
on开头的称位DOM0级事件处理程序,因为简单和跨浏览器现在还在使用
1
2
3
4
5
6
|
var btn =
document.getElementById(
"app")l
btn.onclick =
function(){
console.log(
this)
}
|
DOM2级事件处理程序
DOM2级事件处理程序就是我们经常使用的事件监听:addEventListener()和removeEventListener(),
他们介绍三个参数,事件类型,事件回调函数(事件处理程序),一个布尔值,最后一个参数是True或false ,true代表在捕获阶段调用回调,false代表在冒泡阶段调用回调。
1
2
3
4
5
6
7
8
9
|
var btn =
document.getElementById(
"app")l
btn.addEventListener(
'click',
function(){
console.log(
this)
},
false)
btn.removeEventListener(
'click',
function(){
console.log(
this)
},
false)
|
DOM2级事件处理程序可以为元素添加加多个事件,并且按照添加的顺序执行这个是他的一大特点
IE事件处理程序
IE在监听事件必须用他自己的方法(IE没办法人家先出,先做了自己的):attachEvent(),detachEvent()他们都接受2个参数:事件类型,和事件处理函数。但是必须用具有特色的IE on名称 类型。
1
2
3
4
5
6
7
8
9
10
11
12
|
var btn =
document.getElementById(
"app")l
btn.attachEvent(
'onclick',
function(){
console.log(
this)
})
btn.attachEvent(
'onclick',
function(){
console.log(
'SECEND')
})
btn.detachEvent(
'onclick',
function(){
console.log(
this)
})
|
IE中的时间处理程序有2个特别不同的地方
1.顺序和DOM不同的是相反,先添加后执行
2.代码中的this指向不同,IE指向window、DOM指向目标元素作用域
既然有这么多不同的浏览器支持的情况不一样我们通常情况下都会进行封装让我们执行的程序在不同浏览器上面看起来是一样的
我们来写一个EventUtil工具
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
var EventUtil = {
addEvent:
function (el, eventType, fn) {
if (el.addEventListener) {
el.addEventListener(eventType, fn,
false);
}
else
if (el.attachEvent) {
el.attachEvent(
'on' + eventType, fn);
}
else {
el[
'on' + eventType] = fn;
}
},
removeEvent:
function (el, eventType, fn) {
if (el.removeEventListener) {
el.removeEventListener(eventType, fn,
false);
}
else
if (el.detachEvent) {
el.detachEvent(
'on' + eventType, fn);
}
else {
el[
'on' + eventType] =
null;
}
}
}
|
事件对象
在触发一个事件时会生成一个事件对象Event
Event里面有很多事件对象点击查看
我们只讲讲我们常用的 阻止默认行为 preventDefault ,阻止捕获或者冒泡 stopPropagation
当然又要说到我们的IE了,阻止默认行为 returnValue = false,阻止捕获或者冒泡 cancelBubble
让我们进一步对上面的EventUtil进行封装
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
33
34
35
36
37
38
39
40
|
var EventUtil = {
addEvent:
function (el, eventType, fn) {
//绑定事件
if (el.addEventListener) {
el.addEventListener(eventType, fn,
false);
}
else
if (el.attachEvent) {
el.attachEvent(
'on' + eventType, fn);
}
else {
el[
'on' + eventType] = fn;
}
},
removeEvent:
function (el, eventType, fn) {
//移除事件
if (el.removeEventListener) {
el.removeEventListener(eventType, fn,
false);
}
else
if (el.detachEvent) {
el.detachEvent(
'on' + eventType, fn);
}
else {
el[
'on' + eventType] =
null;
}
},
getEvent:
function (ev) {
//获取事件对象
return ev ? ev :
window.ev;
},
getTarget:
function (ev) {
//获取元素
return ev.target || ev.srcElement;
},
preventDefault:
function (e) {
//阻止默认行为
if (ev.preventDefault) {
ev.preventDefault();
}
else {
ev.returnValue =
false;
}
},
stopPropagation:
function (ev) {
//阻止冒泡或捕获
if (ev.stopPropagation) {
ev.stopPropagation();
}
else {
ev.cancelBubble =
true;
}
}
}
|
内存和性能
给原生绑定事件是要消耗内存的,所以在一些大量相同事件我们可以经过事件委托和移除事件处理程序来处理
事件委托
事件委托是利用了时间冒泡,只指定一个事件处理程序,就能管理某一类的所有时间
具体使用方法可以查看我原来写的一篇文章使用事件代理来优化dom事件的绑定
绑定的事件少了,占用的内存也就少了,时间也少了。
移除事件处理程序
内存中留有那些过时的不同的“空事件程序”我们应该清除掉,如果不清除就占用了内存和出现性能问题
清除方法
1
|
btn.onclick=
null
|
此文中对事件只是一部分的记录,正真的DOM事件还包括事件类型等!