1、事件流
事件流指的是从页面中接收事件的顺序。分为冒泡流和捕获流。
DOM二级事件规定事件流包括三个阶段:
1、事件捕获阶段
2、处于目标阶段
3、事件冒泡阶段
DOM在触发事件后,会经历事件捕获和事件冒泡两个最重要阶段。
2、事件冒泡
由最里层向最外层触发事件的过程,叫事件冒泡。
例1:事件冒泡测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.parent {
width: 300px;
height: 200px;
background-color: #f00;
}
.child {
width: 200px;
height: 100px;
background-color: #ff0;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">Please click me!</div>
</div>
</body>
<script>
var parent = document.getElementsByClassName('parent')[0];
var child = document.getElementsByClassName('child')[0];
child.addEventListener('click', function () {
console.log('child')
}, false) // false:表示事件冒泡 true:表示事件捕获
parent.addEventListener('click', function () {
console.log('parent')
}, false)
document.body.addEventListener('click', function () {
console.log('body')
}, false)
document.addEventListener('click', function () {
console.log('document')
}, false)
window.addEventListener('click', function () {
console.log('window')
}, false)
</script>
</html>
如果单击了div,事件会按child->parent->body->document->window顺序触发,相当于逐级向上触发,这种情况叫事件冒泡。
3、事件捕获
由最外层向最里层触发事件的过程,叫事件捕获。
语法:DOM.addEventListener('事件名',callback,true)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.parent {
width: 300px;
height: 200px;
background-color: #f00;
}
.child {
width: 200px;
height: 100px;
background-color: #ff0;
}
</style>
<body>
<div class="parent">
<div class="child">Please click me!</div>
</div>
</body>
<script>
var parent = document.getElementsByClassName('parent')[0];
var child = document.getElementsByClassName('child')[0];
child.addEventListener('click', function () {
console.log('child')
}, true) // false:表示事件冒泡 true:表示事件捕获
parent.addEventListener('click', function () {
console.log('parent')
}, true)
document.body.addEventListener('click', function () {
console.log('body')
}, true)
document.addEventListener('click', function () {
console.log('document')
}, true)
window.addEventListener('click', function () {
console.log('window')
}, true)
</script>
</html>
由最外层向最里层触发事件的过程,叫事件捕获,这个过程与事件冒泡的过程是相反的,如果想要把事件冒泡改为事件捕获,要用addEventListener去写事件监听,不要直接用onXXX事件去写,将触发的子元素的父元素以上的元素的事件后用true实现。
4、阻止冒泡
var e = e || window.event;
e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true; // 阻止事件冒泡兼容写法
e.stopPropagation(); // 不考虑兼容的写法
例3:测试阻止冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.parent {
width: 300px;
height: 200px;
background-color: #f00;
}
.child {
width: 200px;
height: 100px;
background-color: #ff0;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">Please click me!</div>
</div>
</body>
<script>
var parent = document.getElementsByClassName('parent')[0];
var child = document.getElementsByClassName('child')[0];
child.addEventListener('click', function (e) {
var e = e || window.event;
e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true; // 阻止事件冒泡兼容写法
console.log('child')
}, false)
parent.addEventListener('click', function (e) {
e.stopPropagation(); // 不考虑兼容的写法
console.log('parent')
}, false)
document.body.addEventListener('click', function () {
console.log('body')
}, false)
document.addEventListener('click', function () {
console.log('document')
}, false)
window.addEventListener('click', function () {
console.log('window')
}, false)
</script>
</html>
5.事件委托
将所有子元素的事件写到(委托)父元素上,这样的过程叫事件委托。
使用场景:
1、将多个子元素的事件委托给父元素完成(基于性能优化的考虑)
2、在动态加进来元素上绑定事件
例4:测试事件委托
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul class="list">
<li>li01</li>
<li>li02</li>
<li>li03</li>
<li>li04</li>
<li>li05</li>
</ul>
</body>
<script src="event.js"></script>
<script>
var lis = document.getElementsByClassName('list')[0]
eventDeal.addHandler(lis, 'click', function (event) {
//获取事件对象
event = eventDeal.getEvent(event)
//获取目标对象
var target = eventDeal.getTarget(event)
target.style.color = 'red'
target.innerHTML += 'aaaa'
})
</script>
</html>
event.js中的代码
var eventDeal = {
//event对象兼容处理
getEvent: function (event) {
return event || window.event
},
//目标对象兼容处理
getTarget: function (event) {
return event.target || event.srcElement
},
//绑定事件兼容处理
addHandler: function (element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false)
} else if (element.attachEvent) {//兼容IE低版本
element.attachEvent('on' + type, handler)
} else {
element['on' + type] = handler
}
}
}