事件
1 事件对象简介
- 事件对象是由浏览器在事件触发时所创建的对象,这个对象中封装了事件相关的各种信息
- 通过事件对象可以获取到事件的详细信息比如:鼠标的坐标、键盘的按键…
- 浏览器在创建事件对象后,会将事件对象作为响应函数的参数传递,所以我们可以在事件的回调函数中定义一个形参来接收事件对象
案例:获取鼠标的坐标
const box1 = document.getElementById("box1")
// 下面两种方式都可以拿到事件对象
// box1.onmousemove = event => {
// console.log(event)
// }
box1.addEventListener("mousemove", event => {
console.log(event.clientX, event.clientY)
box1.textContent = event.clientX + "," + event.clientY
})
2 Event对象
Event - Web API 接口参考
- 在DOM中存在着多种不同类型的事件对象,多种事件对象有一个共同的祖先 Event
- event.target 触发事件的对象
- event.currentTarget 绑定事件的对象(同this)
- event.stopPropagation() 停止事件的传导
- event.preventDefault() 取消默认行为
- 事件的冒泡(bubble)
- 事件的冒泡就是指事件的向上传导
- 当元素上的某个事件被触发后,其祖先元素上的相同事件也会同时被触发
- 冒泡的存在大大的简化了代码的编写,但是在一些场景下我们并不希望冒泡存在不希望事件冒泡时,可以通过事件对象来取消冒泡
案例:阻止事件冒泡
- 点击最小的div不会向外冒泡,点击中间的div会向外冒泡
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Document</title>
<style>
#box1 {
width: 300px;
height: 300px;
background-color: greenyellow;
}
#box2 {
width: 250px;
height: 250px;
background-color: #ff0;
}
#box3 {
width: 200px;
height: 200px;
background-color: orange;
}
</style>
</head>
<body>
<div id="box1">
<div id="box2">
<div id="box3"></div>
</div>
</div>
<script>
const box1 = document.getElementById("box1")
const box2 = document.getElementById("box2")
const box3 = document.getElementById("box3")
box1.addEventListener("click", function (event) {
alert("Hello 我是box1")
})
box2.addEventListener("click", function (event) {
alert("我是box2")
})
box3.addEventListener("click", function (event) {
event.stopPropagation() // 取消事件的传到
alert("我是box3")
})
</script>
</body>
</html>
案例:取消超链接的默认跳转行为
const link = document.querySelector("a")
link.addEventListener("click", (event) => {
event.preventDefault() // 取消默认行为
alert("被点了~~~")
})
3 冒泡
- 取消冒泡:
event.stopPropagation()
案例:图标跟随鼠标
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#box {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #8cdb69;
position: absolute;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
const box = document.querySelector("#box")
document.addEventListener("mousemove", (event) => {
box.style.top = event.y - 10 + 'px'
box.style.left = event.x - 10 + 'px'
})
</script>
</body>
</html>
案例:在一片区域中图标不跟随鼠标(使用阻止冒泡事件实现效果)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#box {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #8cdb69;
position: absolute;
}
#box2 {
width: 400px;
height: 400px;
background-color: black;
}
</style>
</head>
<body>
<div id="box"></div>
<div id="box2"></div>
<script>
const box = document.querySelector("#box")
const box2 = document.querySelector("#box2")
document.addEventListener("mousemove", (event) => {
box.style.top = event.y + 'px'
box.style.left = event.x + 'px'
})
box2.addEventListener("mousemove", (event) => {
event.stopPropagation()
})
</script>
</body>
</html>
4 事件的委派
委派就是将本该绑定给多个元素的事件,统一绑定给父级元素,这样可以降低代码复杂度方便维护
案例:点击li标签,打印出其中的内容
思路:原来是通过在每一个li上都绑定一个点击事件,然后对新加的li也再添加事件,但是现在可以使用事件的委派来实现这个操作,也就是直接绑定在父级元素上
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
ul {
background-color: orange;
width: 100px;
}
</style>
</head>
<body>
<ul>
<li>链接1</li>
<li>链接2</li>
<li>链接3</li>
<li>链接4</li>
</ul>
<script>
const ul = document.querySelector("ul")
ul.addEventListener("click", event => {
alert(event.target.innerText)
})
</script>
</body>
</html>
5 事件的捕获
事件的传播机制
- 在DOM中,事件的传播可以分为三个阶段:
- 捕获阶段 (由祖先元素向目标元素进行事件的捕获)(默认情况下,事件不会在捕获阶段触发)
- 目标阶段 (触发事件的对象)
- 冒泡阶段 (由目标元素向祖先元素进行事件的冒泡)
- 事件的捕获,指事件从外向内的传导,当前元素触发事件以后,会先从当前元素最大的祖先元素开始向当前元素进行事件的捕获
- 如果希望在捕获阶段触发事件,可以将addEventListener的第三个参数设置为true
- 一般情况下我们不希望事件在捕获阶段触发,所有通常都不需要设置第三个参数
通过
event.eventPhase
可以获得事件触发的阶段1 捕获阶段 2 目标阶段 3 冒泡阶段
- 捕获:由外向里传播
- 冒泡:由里向外传播
- 使用
stopPropagation()
可以停止捕获或者冒泡,在执行到的函数停止
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
#box1 {
width: 300px;
height: 300px;
background-color: greenyellow;
}
#box2 {
width: 200px;
height: 200px;
background-color: orange;
}
#box3 {
width: 100px;
height: 100px;
background-color: tomato;
}
</style>
</head>
<body>
<div id="box1">
<div id="box2">
<div id="box3"></div>
</div>
</div>
<script>
const box1 = document.getElementById("box1")
const box2 = document.getElementById("box2")
const box3 = document.getElementById("box3")
box1.addEventListener("click", event => {
alert("1" + event.eventPhase) // eventPhase 表示事件触发的阶段
//1 捕获阶段 2 目标阶段 3 冒泡阶段
})
box2.addEventListener("click", event => {
alert("2" + event.eventPhase)
})
box3.addEventListener("click", event => {
alert("3" + event.eventPhase)
})
</script>
</body>
</html>