事件的传播
事件的传播
+ 当你在一个元素上触发行为的时候
=> 会按照 结构父级 的顺序向上传播 行为(是行为,不是事件处理函数)
=> 直到 window 为止
利用事件的传播的例子
+ img外面包个a标签, 点击img跳转链接
<div class="outer">
<div class="center">
<div class="inner"></div>
</div>
</div>
<p class="other"></p>
+ 问题1:
=> 当我点击 inner 的时候,给 从 inner 到 window 的所有都绑定一个点击事件
=> 会不会都触发?
=> 会
+ 问题2:
=> 当我点击在 inner 的时候, inner 自己没有事件处理函数
=> 结构父级上的处理函数会不会触发?
=> 会
+ 问题3:
=> 当我点击在 outer 的时候, inner 和 center 的事件会不会触发
=> 不会
+ 问题4:
=> 当我点击 other 的时候, inner, center, outer的事件会不会触发?
=> 不会
=> 当我点击 other 的时候, body 的事件会不会触发?
=> 会
+ 问题5:
=> 当我在 inner 身上触发一个移入事件的时候
=> 会不会触发 center 的点击事件?
=> 不会, 只能触发同类型事件
var other = document.querySelector('.other')
other.addEventListener('click', function(){console.log('other的点击事件')})
// 0. 获取元素
var inner = document.querySelector('.inner')
// 1. 绑定点击事件
inner.addEventListener('click', function(){
console.log('inner的点击事件')
})
inner.addEventListener('mouseover', function(){console.log('inner的移入事件')})
var center = document.querySelector('.center')
center.addEventListener('click', function(){console.log('center的点击事件')})
var outer = document.querySelector('.outer')
outer.addEventListener('click', function(){console.log('outer的点击事件')})
document.body.addEventListener('click', function(){console.log('body的点击事件')})
document.documentElement.addEventListener('click', function(){console.log('html的点击事件')})
document.addEventListener('click', function(){console.log('document的点击事件')})
window.addEventListener('click', function(){console.log('window的点击事件')})
+ 定义:
=> 当事件触发的时候,会按照结构父级的顺序向上传递同类型的事件
=> 事件对象里面有一个信息叫做 path, 表示当前事件传播的路径
var other = document.querySelector('.other')
other.addEventListener('click', function(){console.log('other的点击事件')})
// 0. 获取元素
var inner = document.querySelector('.inner')
// 1. 绑定点击事件
inner.addEventListener('click', function(e){
console.log('inner的点击事件')
console.log(e.path)
})
// inner.addEventListener('mouseover', function(){console.log('inner的移入事件')})
var center = document.querySelector('.center')
center.addEventListener('click', function(){console.log('center的点击事件')})
var outer = document.querySelector('.outer')
outer.addEventListener('click', function(){console.log('outer的点击事件')})
document.body.addEventListener('click', function(){console.log('body的点击事件')})
document.documentElement.addEventListener('click', function(){console.log('html的点击事件')})
document.addEventListener('click', function(){console.log('document的点击事件')})
window.addEventListener('click', function(){console.log('window的点击事件')})
事件的目标冒泡和捕获
目标
=> 准确触发事件的那个元素
=> 当你给 center 绑定一个点击事件
-> 你点击 inner 会触发
-> 你点击 center 也会触发
-> 两次事件触发的元素是不一样的
=> 在事件对象里面有一个属性叫做 target
-> 表示本次事件触发的时候,准确触发的元素
-> 我们叫做事件目标
=> IE 低版本不支持
-> IE 低版本使用 srcElement
=> 处理兼容
-> var target = e.target || e.srcElement
<div class="outer">
<div class="center" id="center">
<div class="inner"></div>
</div>
</div>
// 0. 获取元素
var center = document.querySelector('.center')
center.addEventListener('click', function(e){
console.log('center的点击事件')
console.log(e.target)
})
// IE 低版本
var center = document.getElementById('center')
center.attachEvent('onclick', function(e){
console.log('center的点击事件')
// console.log(e.srcElement)
// 处理兼容
var target = e.target || e.srcElement
console.log(target)
})
冒泡
冒泡和捕获只是触发事件的顺序不同
=> 按照从 目标 到 window 的顺序来执行所有的事件
捕获
=> 按照从 window 到 目标 的顺序来执行所有的事件
addEventListener() 的第三个参数
-> 默认是 false, 表示冒泡
-> 可以选填 true , 表示捕获
// 1. 绑定点击事件
inner.addEventListener('click', function(e){
console.log('inner的点击事件')
console.log(e.path)
}, true)
var center = document.querySelector('.center')
center.addEventListener('click', function(){
console.log('center的点击事件')
}, true)
var outer = document.querySelector('.outer')
outer.addEventListener('click', function(){
console.log('outer的点击事件')
}, true)
document.body.addEventListener('click', function(){
console.log('body的点击事件')
}, true)
document.documentElement.addEventListener('click', function(){
console.log('html的点击事件')
}, true)
document.addEventListener('click', function(){
console.log('document的点击事件')
}, true)
window.addEventListener('click', function(){
console.log('window的点击事件')
}, true)
移入移出事件的区别
1.
mouseover 移入
mouseout 移出
2.
mouseenter 移入
mouseleave 移出
+ 行为: 都是移入行为和移出行为会触发
+ 事件: enter 和 leave 不会进行事件传播
<style>
.outer{
width: 500px;
height: 500px;
background-color: skyblue;
}
.inner{
width: 300px;
height: 300px;
background-color: pink;
}
</style>
<div class="outer">
<div class="inner"></div>
</div>
var inner = document.querySelector('.inner')
var outer = document.querySelector('.outer')
// over 和 out 会传播事件
// outer.addEventListener('mouseover', function(){console.log('鼠标移入')})
// outer.addEventListener('mouseout', function(){console.log('鼠标移出')})
// enter 和 leave 不会传播事件
outer.addEventListener('mouseenter', function(){console.log('鼠标移入')})
outer.addEventListener('mouseleave', function(){console.log('鼠标移出')})
阻止事件传播
+ 因为事件的传播, 会导致我在一个元素上触发行为时
+ 会执行多个元素的事件处理函数
+ 阻止事件传播
1. e.stopPropagation()
=> 标准浏览器使用
2. e.cancleBubble = true
=> IE 低版本使用
兼容:
方式1: if(e.stopPropagation){} else{}
方式2: try{} catch(e){}
var inner = document.getElementById('inner')
var outer = document.getElementById('outer')
inner.onclick = function(e){
// 事件对象兼容
e = e || window.event
console.log('inner的点击事件')
// 阻止事件传播
// 这个代码一旦执行, 从这个元素开始, 行为不再向上传播
// 标准浏览器
// e.stopPropagation()
// IE 低版本
// e.cancelBubble = true
}
// 兼容: 方式一
if(e.stopPropagation){
e.stopPropagation()
}else{
e.cancleBubble = true
}
}
outer.onclick = function(){
console.log('outer的点击事件')
}
// try catch 语法
// 如果 try 里面的代码没有报错, 那么 catch 不执行
// 如果 try 里面的代码报错, 那么执行 catch 里面的代码
// => 在 catch 接收的 e 参数表示 try 里面的报错信息error
// try{
// console.log('尝试的代码')
// // throw new Error('报个错')
// } catch(err){
// console.log('备用的代码')
// console.log(err)
// }
// 兼容: 方式二
try{
e.stopPropagation()
} catch(err){
e.cancleBubble = true
}