事件冒泡:

只要结构上,非视觉上嵌套关系的元素,或存在事件冒泡的功能,即同一事件,自子元素冒泡到父元素。

如:当点击子元素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)

事件冒泡、事件捕获、取消冒泡、取消默认事件_事件对象_02

 

如果同时定义事件捕获和事件冒泡,执行顺序为:

永远是:先捕获后冒泡,不管执行顺序如何颠倒,但是事件传递到点击的子元素时,此时是事件执行,因为点击的就是子元素本身,所以,下边当点击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)

事件冒泡、事件捕获、取消冒泡、取消默认事件_封装_03

 

取消事件冒泡:

event.stopPropagation( ) IE9及以下不支持

IE: event.cancelBubble = true

content.addEventListener('click', function(e) {
console.log('content - 冒泡')
e.stopPropagation()
}, false)

事件冒泡、事件捕获、取消冒泡、取消默认事件_事件冒泡_04

封装 取消冒泡/捕获方法:

// 需要传一个事件对象
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
}
}