目录
1.事件对象
1.1获取事件对象
1.2事件对象常用属性
2.事件流
1.1事件流的两个阶段:冒泡和捕获
1.2阻止事件流动
1.3阻止默认行为
1.4两种注册事件的区别
3.事件委托
1.事件对象
1.1获取事件对象
事件对象:也是一个对象,这个对象里有事件触发时的相关信息
例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置的信息
获取事件对象:
- 在事件绑定的回调函数的第一个参数就是事件对象
- 一般命名为event,ev,e
语法:元素.addEventListener('click', function(e) { }) e就是事件对象
1.2事件对象常用属性
常用属性
- type:获取当前事件类型
- clientX/clientY:获取光标相对于浏览器可见窗口左上角的位置
- pageX/pageY:获取光标相对于浏览器窗口左上角的位置
- offsetX/offsetY:获取光标相对于当前DOM元素左上角的位置
- key:用户按下的键盘键的值(现在不再使用keyNode)
案例:图片跟随鼠标
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
img {
position: absolute;
top: 0;
left: 0;
}
</style>
</head>
<body>
<img src="./pictures/tianshi.gif" alt="">
<script>
let img = document.querySelector('img')
document.addEventListener('mousemove', function(e) {
// 鼠标坐标赋值给图片
// 减值是为了让鼠标在图片上面
img.style.left = e.pageX - 50 + 'px'
img.style.top = e.pageY - 40 + 'px'
})
</script>
</body>
</html>
2.事件流
1.1事件流的两个阶段:冒泡和捕获
事件流:事件完整执行过程中的流动路径
假设页面里有一个div,当触发事件时,会经历两个阶段:捕获阶段和冒泡阶段
①事件冒泡:
当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发(依次向上调用所有父级元素的同名事件),这一过程称为事件冒泡
📖Note:
- 事件冒泡是默认存在的
②事件捕获:
从DOM的根元素开始去执行对应的事件(从外到里)
📖Note:
- 事件捕获需要写对应的代码才能看到
- DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制),第三个参数传入true代表是捕获阶段触发(不常用),传入false代表冒泡阶段触发,默认false
- 若是用L0事件监听,则只有冒泡阶段,没有捕获阶段
捕获:父级到子级 冒泡:子级到父级
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.grand {
margin: 100px;
width: 500px;
height: 500px;
background-color: red;
}
.father {
width: 400px;
height: 400px;
background-color: pink;
}
.son {
width: 200px;
height: 200px;
background-color: skyblue;
}
</style>
</head>
<body>
<div class="grand">
<div class="father">
<div class="son"></div>
</div>
</div>
<script>
let grand = document.querySelector('.grand')
let father = document.querySelector('.father')
let son = document.querySelector('.son')
grand.addEventListener('click', function(e) {
alert('爷爷级元素的点击事件')
})
father.addEventListener('click', function() {
alert('父级元素的点击事件')
})
son.addEventListener('click', function() {
alert('子级元素的点击事件')
})
</script>
</body>
</html>
上面的案例中,当点击子级元素时,先触发子级元素的绑定的点击事件,再依次向上触发父级元素绑定的点击事件,依次类推,直到访问完所有的父级元素,这个过程即为事件冒泡
事件捕获的过程同理:只不过是从根元素向下访问所有的子级元素
1.2阻止事件流动
冒泡模式默认存在,可能会导致事件影响到父级元素;若想把事件限制在当前元素内,就要阻止事件流动
语法:时间对象.stopPropagation()
📖Note:
- 阻止事件流动需要拿到事件对象,因此回调函数的形参列表必须写e/event
上面的案例中:组织事件流动后,当点击子级元素时,只触发子级元素的点击事件,不会触发父级元素的点击事件
📖Note:鼠标经过事件
- mouseover和mouseout会有冒泡效果
- mouseenter和mouseleave没有冒泡效果(推荐)
1.3阻止默认行为
默认行为,比如链接点击不跳转,表单域的跳转
语法:e.preventDefault()
1.4两种注册事件的区别
两种注册事件的区别:
传统on注册(L0)
- 同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
- 直接使用null覆盖偶就可以实现事件的解绑
- 都是冒泡阶段执行的
事件监听注册(L2)
- 语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)、
- 后面注册的事件不会覆盖前面注册的事件(同一个事件)
- 可以通过第三个参数去确定是在冒泡或者捕获阶段执行
- 必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
- 匿名函数无法被解绑
3.事件委托
利用事件流的特征解决一些开发需求
场景:多个子级元素进行同样的操作时,可以将这个操作委托给父级元素;比如所有的子级元素都要绑定点击事件,则可以给它们的父级添加点击事件,由于冒泡模式默认存在,所以当自身没有绑定点击事件时,会触发父级的点击事件
获取点击的对象,语法:e.target
获取点击的对象的名字,语法:e.target.tagName