事件冒泡:
只要结构上,非视觉上嵌套关系的元素,或存在事件冒泡的功能,即同一事件,自子元素冒泡到父元素。
如:当点击子元素content时,会向上依次执行(自底向上冒泡):
<div class="wrapper">
<div class="box">
<div class="content"></div>
</div>
</div>
<script>
let wra = document.getElementsByClassName('wrapper')[0]
let box = document.getElementsByClassName('box')[0]
let content = document.getElementsByClassName('content')[0]
wra.addEventListener('click', function() {
console.log('wrapper')
}, false)
box.addEventListener('click', function() {
console.log('box')
}, false)
content.addEventListener('click', function() {
console.log('content')
}, false)
</script>
事件捕获:
跟事件冒泡正好相反,结构上嵌套关系的元素,存在事件捕获,当点击子元素content时,执行顺序是自父元素到子元素, 开启捕获,ele.addEventListener('type', Fn, true) 参数三改为 true即可开启捕获功能(自顶向下):
wra.addEventListener('click', function() {
console.log('wrapper')
}, true)
box.addEventListener('click', function() {
console.log('box')
}, true)
content.addEventListener('click', function() {
console.log('content')
}, true)
如果同时定义事件捕获和事件冒泡,执行顺序为:
永远是:先捕获后冒泡,不管执行顺序如何颠倒,但是事件传递到点击的子元素时,此时是事件执行,因为点击的就是子元素本身,所以,下边当点击content子元素时,先捕获是没问题的,到了content时,遵循的是事件的执行顺序,也就是哪一个事件先绑定的,哪一个先执行,冒泡事件先绑定,先输出 'content - 冒泡' ,之后 输出 'content - 捕获' ,然后接着向上冒泡 。。。:
let wra = document.getElementsByClassName('wrapper')[0]
let box = document.getElementsByClassName('box')[0]
let content = document.getElementsByClassName('content')[0]
wra.addEventListener('click', function() {
console.log('wrapper')
}, false)
box.addEventListener('click', function() {
console.log('box')
}, false)
content.addEventListener('click', function() {
console.log('content')
}, false)
wra.addEventListener('click', function() {
console.log('wrapper')
}, true)
box.addEventListener('click', function() {
console.log('box')
}, true)
content.addEventListener('click', function() {
console.log('content')
}, true)
取消事件冒泡:
event.stopPropagation( ) IE9及以下不支持
IE: event.cancelBubble = true
content.addEventListener('click', function(e) {
console.log('content - 冒泡')
e.stopPropagation()
}, false)
封装 取消冒泡/捕获方法:
// 需要传一个事件对象
function cancelBubble(e) {
if (e.cancelBubble) {
e.cancelBubble = true
}else {
// e.stopPropagation()
e.stopPropagation()
}
}
实际开发:
取消冒泡在实际开发非常常用,只不过一些框架都帮你封装好了,这一点你需要理解。
取消默认事件:
3种方式:
1、return false ( 注意: 只有句柄的方式 dom.onclick 绑定的事件才好使,addEventListener 不好使!!!)
2、e.preventDefault( ) IE9 及以下不兼容
3、e.returnValue = false IE兼容
封装 阻止默认事件方法:
function cancelHandler(e) {
if (e.preventDefault) {
e.preventDefault()
} else {
e.returnValue = false
}
}
补充:只有cancelable 属性设置为true时,才可以使用 preventDefault()来取消其默认行为。
扩展:
一、取消a标签的默认事件:
方法1:
a.onclick = function() {
return false
}
方法2:
括号里边false 或0 都行
<a href="javascript:void(false)">click</a>
二、兼容事件对象
在老版本ie浏览器,没有事件对象e,但是 存在window.event.
所以,原生开发中会这样写:
dom.onclick = function (e) {
let e = e || window.event
}
三、事件源 - 事件对象上有一个属性,专门记录事件源的
所为的事件源,就是点击的哪一个元素,事件源就是谁。。。
(1)event.target 火狐只有这个
(2)event.srcElement IE只有这个
谷歌两个都有。
封装兼容方法:
function handleTarget(e) {
let event = e || window.event
if (event.target) {
return event.target
} else {
return event.srcElement
}
}