事件流
事件流描述的是从页面中接收事件的顺序,也可理解为事件在页面中传播的顺序。事件流分为事件冒泡和事件捕获。关于为什么会有事件冒泡和事件捕获,还有一个小故事:
浏览器开发团队中的IE认为事件传递的顺序应该是点击目标元素然后向外扩散,网景公司团队认为事件传递应该是先点击了最外面的元素,然后最后传递到目标元素,有兴趣的可以下去科普一下。
事件冒泡是指目标元素逐级向上传递的过程
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body id="body">
<div id="box" style="width:100px;height:100px;background:red"></div>
</body>
<script>
box.onclick=function(){
console.log('box')
}
body.onclick=function(){
console.log('body')
}
window.onclick=function(){
console.log('window')
}
//会依次输出box body window
box.addEventListener('click', function () {
console.log('box')
})
body.addEventListener('click', function () {
console.log('body')
})
window.addEventListener('click', function () {
console.log('window')
})
//addEventListener方法的第三个参数是一个布尔值,默认是false,即事件冒泡,反之
//是事件捕获,为false的时候跟绑定一个事件处理函数是一样的,都是事件冒泡,输出依然
//是box、body、window,为true的时候是事件捕获。
box.addEventListener('click', function () {
console.log('box')
},true)
})
body.addEventListener('click', function () {
console.log('body')
},true)
window.addEventListener('click', function () {
console.log('window')
},true)
//window body box
</script>
</html>
阻止事件冒泡
阻止事件冒泡有bubbles、stopPropagation、stopImmediatePropagation、cancleBubble几种方式,但是stopPropagation和stopImmediatePropagation是有兼容性的,最低兼容到IE8(不包括),js中大部分事件都是会冒泡的,onfocus、onblur、onscroll事件除外
1、event对象中的bubbles属性可以检测发生的事件是否是一个起泡事件
box.addEventListener('click', function (e) {
console.log('box1')
console.log(e.bubbles)
//返回true表示是事件冒泡,反之是事件捕获
})
2、使用event对象中的stopPropagation方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body id="body">
<div id="box" style="width:100px;height:100px;background:red"></div>
</body>
<script>
box.addEventListener('click', function (e) {
console.log('box')
e.stopPropagation();
})
body.addEventListener('click', function () {
console.log('body')
})
window.addEventListener('click', function () {
console.log('window')
})
// box
//注意e.stopPropagation方法不仅可以阻止事件冒泡,还可以阻止事件捕获
box.addEventListener('click', function (e) {
console.log('box')
e.stopPropagation();
})
body.addEventListener('click', function () {
console.log('body')
})
window.addEventListener('click', function (e) {
console.log('window')
e.stopPropagation()
}.true)
//window
</script>
</html>
2、使用event对象中stopImmediatePropagation方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body id="body">
<div id="box" style="width:100px;height:100px;background:red"></div>
</body>
<script>
box.addEventListener('click', function (e) {
console.log('box1')
})
box.addEventListener('click',function(){
console.log('box2')
})
body.addEventListener('click', function () {
console.log('body')
})
window.addEventListener('click', function (e) {
console.log('window')
})
//会输出box1,box2,body,window
-----------------使用stopImmediatePropagation方法-----------------
box.addEventListener('click', function (e) {
console.log('box1')
e.stopImmediatePropagation()
})
box.addEventListener('click',function(){
console.log('box2')
})
body.addEventListener('click', function () {
console.log('body')
})
window.addEventListener('click', function (e) {
console.log('window')
})
//这里只会输出了box1,可以看出stopImmediatePropagation方法不仅可以阻止事件冒泡和事件捕获,
//还可以阻止给同一个don元素绑定的事件处理函数
</script>
</html>
4、使用event对象中的cancleBubble属性
box.addEventListener('click', function (e) {
console.log('box')
e.cancelBubble = true
})
body.addEventListener('click', function () {
console.log('body')
})
window.addEventListener('click', function (e) {
console.log('window')
})
//box
判断兼容性
function cancalBubble(e) {
let e = e || window.event;
if (e.stopPropagation) {
e.stopPropagation()
} else {
e.cancelBubble = true;
}
}