一、事件传播
假设我们在浏览器内用一个宽高500px的盒子,内部有一个水平垂直都居中的子级盒子,宽高为100px
当我点击在子级盒子上的时候,其实也是点击在了这个父级盒子的身上
这种情况就叫做事件传播
- 当元素触发一个事件的时候,这个元素的父级节点也会触发相同的事件,父元素的父元素也会触发相同的事件
- 点击了子级盒子,会触发子级盒子的点击事件
- 也是点在了父级盒子上,也会触发父级盒子的点击事件
- 也是点在了 body 上,也会触发 body 的点击事件
- 也是点在了 html 上,也会触发 html 的点击事件
- 也是点在了 document 上,也会触发 document 的点击事件
- 也是点在了 window 上,也会触发 window 的点击事件
- 页面上任何一个元素触发事件,都会一层一层的最终导致window的相同事件触发
- 前提是一定得有事件
注意点:
- 1.只会传播同类事件,如果是点击事件,那么只会触发父级或者父级的父级注册的点击事件,其他类型的事件不会触发
- 2.只会从点击的元素开始,按照html的结果,逐层向上触发同类型的事件
- 3.内部元素不管有没有该事件,只要上层元素有该事件,那么上层元素的事件就会触发
<html>
<style>
*{
margin: 0;
padding: 0;
}
.box {
width: 300px;
height: 300px;
background-color: pink;
}
.sBox {
width: 100px;
height: 100px;
background-color: green;
}
</style>
<body>
<div class="box">
<div class="sBox"></div>
</div>
<script>
// 0. 获取元素
var sBox = document.querySelector('.sBox')
var box = document.querySelector('.box')
var oBody = document.body
sBox.onclick = function () {
console.log('我是内层div,我的点击事件被触发了')
}
box.onclick = function () {
console.log('我是外层div,我的点击事件被触发了')
}
oBody.onclick = function () {
console.log('我是body,我的点击事件被触发了')
}
</script>
</body>
</html>
二、事件的冒泡与捕获 目标
目标:你点击在哪个元素上,那么这个事件的目标就是这个元素
事件的冒泡与捕获(面试题)
冒泡:就是从目标的事件处理函数开始,依次向上,一直到window的事件处理函数触发
也就是说从下向上的执行事件处理函数
捕获:就是从window的事件处理函数开始,依次向下,一直到目标的事件处理函数触发
也就是说从上向下的执行事件处理函数
区别:就是在事件的传播中,多个同类型的事件处理函数的执行顺序不同,仅此而已
三、事件委托
就是要把我自己做的事,委托给别人帮我完成
因为我们的冒泡机制,点击子元素的时候,也会同步触发父元素的相同事件
所以我们可以把子元素的事件委托给父元素来做
点击子元素的时候,不管子元素有没有点击事件,只要父元素有点击事件,那么就可以触发父元素的点击事件
target
这个属性是事件对象里的属性,表示你点击的目标
target兼容性有问题,在IE浏览器内需要使用srcElement 语法:e.srcElement (了解即可)
事件委托的优点
-
页面上本身没有li,通过代码添加了一些li
-
这些li是没有点击事件的,每次动态的添加li,还需要重新给li绑定一次点击事件
-
这时候使用事件委托就比较合适
-
因为:新加进来的li也是ul的子元素,点击的时候也可以触发 ul的点击事件
var oUl = document.querySelector('ul')
oUl.onclick = function (e) {
if(e.target.nodeName === 'LI'){
console.log('我是li标签,我被点击了~~~')
}
}
四、默认行为
默认行为:不用我们注册,但是自己存在的事情
比如:鼠标右键单击,会弹出一个菜单
点击a标签后,自己会跳转到页面
这些不需要我们注册就能实现的事情,我们叫做默认事件
阻止默认事件
不希望浏览器执行默认事件时,比如点击a标签,不跳转页面,那么就需要阻止默认事件
两种方式:
1.e.preventDefault() --- 非IE浏览器
2.e.returnValue = false --- IE浏览器(了解即可)
var oA = document.querySelector('a')
oA.onclick = function (e) {
console.log('该函数执行,拦截掉了 a 标签的默认行为')
e.preventDefault()
}