一、单个元素下mouseenter、mouseleave和mouseover、mouseout没有区别
我们先来一个demo,设置一个div
<!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>
.box {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var boxEl = document.querySelector(".box")
// 第一组
boxEl.onmouseenter = function () {
console.log("onmouseenter");
}
boxEl.onmouseleave = function () {
console.log("onmouseleave");
}
// 第二组
boxEl.onmouseover = function () {
console.log("onmouseover");
}
boxEl.onmouseout = function () {
console.log("onmouseout");
}
</script>
</body>
</html>
我们看下鼠标移动上去然后离开的反应:如图展示,
得出结论:单个元素不存在嵌套的情况下,两者是没有区别的。
二、嵌套元素下mouseenter、mouseleave和mouseover、mouseout的区别
(1)案例一:onmouseenter、onmouseleave进入子元素依然属于在父级元素内,没有任何反应。
我们在div里面添加一个span,并设置一个flex布局,从而给span设置宽高。
我们先把onmouseover和onmouseout注释掉,只看onmouseenter和onmouseleave的表现
<!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>
.box {
display: flex;
justify-content: center;
align-items: center;
width: 200px;
height: 200px;
background-color: pink;
}
span {
width: 100px;
height: 100px;
background-color: red;
}
</style>
</head>
<body>
<div class="box">
<span></span>
</div>
<script>
var boxEl = document.querySelector(".box")
// 第一组
boxEl.onmouseenter = function () {
console.log("onmouseenter");
}
boxEl.onmouseleave = function () {
console.log("onmouseleave");
}
// 第二组
// boxEl.onmouseover = function () {
// console.log("onmouseover");
// }
// boxEl.onmouseout = function () {
// console.log("onmouseout");
// }
</script>
</body>
</html>
onmouseenter和onmouseleave在嵌套元素的表现:
当鼠标移动到粉色区域的时候,也触发了onmouseenter事件,
当鼠标从粉色区域(div元素)移动到红色区域(span元素)的时候,没有触发onmouseenter事件,
得出结论:进入子元素依然属于在该元素内,没有任何反应。
(2)案例二:onmouseenter、onmouseleave不支持冒泡
那我们来只监听span的鼠标事件试试看
<!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>
.box {
display: flex;
justify-content: center;
align-items: center;
width: 200px;
height: 200px;
background-color: pink;
}
span {
width: 100px;
height: 100px;
background-color: red;
}
</style>
</head>
<body>
<div class="box">
<span></span>
</div>
<script>
var boxEl = document.querySelector(".box")
var spanEl = document.querySelector("span")
// 第一组
// boxEl.onmouseenter = function () {
// console.log("onmouseenter");
// }
// boxEl.onmouseleave = function () {
// console.log("onmouseleave");
// }
spanEl.onmouseenter = function () {
console.log("span onmouseenter");
}
spanEl.onmouseleave = function () {
console.log("span onmouseleave");
}
// 第二组
// boxEl.onmouseover = function () {
// console.log("onmouseover");
// }
// boxEl.onmouseout = function () {
// console.log("onmouseout");
// }
</script>
</body>
</html>
onmouseenter和onmouseleave在嵌套元素的表现:
当鼠标移动到粉色区域的时候,没有触发了onmouseenter事件,
当鼠标移动到红色区域的时候,触发了onmouseenter事件,
得出结论:onmouseenter、onmouseleave不支持冒泡
(3)案例一和案例二的总结
- onmouseenter、onmouseleave不支持冒泡
- onmouseenter、onmouseleave进入子元素依然属于在父级元素内,没有任何反应。
(4)案例三:onmouseover、onmouseout总结
代码:
<!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>
.box {
display: flex;
justify-content: center;
align-items: center;
width: 200px;
height: 200px;
background-color: pink;
}
span {
width: 100px;
height: 100px;
background-color: red;
}
</style>
</head>
<body>
<div class="box">
<span></span>
</div>
<script>
var boxEl = document.querySelector(".box")
var spanEl = document.querySelector("span")
// 第一组
// boxEl.onmouseenter = function () {
// console.log("box onmouseenter");
// }
// boxEl.onmouseleave = function () {
// console.log("box onmouseleave");
// }
// spanEl.onmouseenter = function () {
// console.log("span onmouseenter");
// }
// spanEl.onmouseleave = function () {
// console.log("span onmouseleave");
// }
// 第二组
boxEl.onmouseover = function () {
console.log("onmouseover");
}
boxEl.onmouseout = function () {
console.log("onmouseout");
}
</script>
</body>
</html>
表现:
当鼠标移动到粉色区域的时候,console.log打印了onmouseover
当鼠标从粉色区域移动到红色区域的时候,console.log打印了onmouseover和onmouseout,说明什么?说明鼠标进入子元素后,告诉我们从父元素离开了,并且span子元素产生了一个事件,又冒泡给div父元素了。
得出结论:
- 支持冒泡
- 进入元素的子元素时
- 先调用父元素的mouseout
- 再调用子元素的mouseover
- 因为支持冒泡,所以会将mouseover传递到父元素中
三、区别
onmouseenter、onmouseleave
- 不支持冒泡
- 进入子元素依然属于在父级元素内,没有任何反应。
onmouseover、onmouseout
- 支持冒泡
- 进入元素的子元素时
- 先调用父元素的mouseout
- 再调用子元素的mouseover
- 因为支持冒泡,所以会将mouseover传递到父元素中
四、案例应用
(1)案例练习一:有一个div,里面有3个button按钮,鼠标移动到哪个按钮上面,就给我console.log对应的元素里面的文本。
<!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>
.box {
width: 300px;
height: 300px;
}
.box button {
height: 50px;
}
</style>
</head>
<body>
<div class="box">
<button>删除</button>
<button>新增</button>
<button>搜索</button>
</div>
</body>
</html>
方案一:监听的本身就是button元素(onmouseover、onmouseenter都可以,这里没区别)
<!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>
.box {
width: 300px;
height: 300px;
}
.box button {
height: 50px;
}
</style>
</head>
<body>
<div class="box">
<button>删除</button>
<button>新增</button>
<button>搜索</button>
</div>
<script>
// 1. 方案一:监听的本身就是button元素
var btnEls = document.querySelectorAll("button")
for (var btnEl of btnEls) {
btnEl.onmouseover = function () {
// 这里不能直接用 btnEl.textContent去拿文本,因为这个时候 btnEl已经执行变成第三个button元素了.
// 在你的代码中,事件处理函数 btnEl.onmouseover 中的 console.log(btnEl.textContent) 会一直输出 "搜索",而不是对应的按钮文本,是因为在 for...of 循环中使用了 var 声明变量 btnEl,导臨了变量提升的问题。这导致在循环结束后,btnEl 指向最后一个按钮元素,即 "搜索" 按钮。
// console.log(btnEl.textContent);
console.log(event.target.textContent);
}
}
</script>
</body>
</html>
弊端:循环的时候,这里创建了三个函数。
怎么优化一下?见方案二
方案二: 事件委托
<!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>
.box {
width: 300px;
height: 300px;
}
.box button {
height: 50px;
}
</style>
</head>
<body>
<div class="box">
<button>删除</button>
<button>新增</button>
<button>搜索</button>
</div>
<script>
// 1. 方案一:监听的本身就是button元素
var btnEls = document.querySelectorAll("button")
// for (var btnEl of btnEls) {
// btnEl.onmouseover = function () {
// // 这里不能直接用 btnEl.textContent去拿文本,因为这个时候 btnEl已经执行变成第三个button元素了.
// // 在你的代码中,事件处理函数 btnEl.onmouseover 中的 console.log(btnEl.textContent) 会一直输出 "搜索",而不是对应的按钮文本,是因为在 for...of 循环中使用了 var 声明变量 btnEl,导臨了变量提升的问题。这导致在循环结束后,btnEl 指向最后一个按钮元素,即 "搜索" 按钮。
// // console.log(btnEl.textContent);
// console.log(event.target.textContent);
// }
// }
// 2. 方案二:事件委托
// var boxEl = document.querySelector(".box")
// boxEl.addEventListener("click", function (event) {
// if (event.target != boxEl) {
// console.log(event.target.textContent);
// }
// }, true)
var boxEl = document.querySelector(".box")
// boxEl.addEventListener("mouseenter", function (event) {
// if (event.target != boxEl) {
// console.log(event.target.textContent);
// }
// }, true)
boxEl.addEventListener("mouseover", function (event) {
if (event.target != boxEl) {
console.log(event.target.textContent);
}
})
</script>
</body>
</html>