需求:二级菜单的显示与隐藏。鼠标移到一级菜单上,会显示二级菜单,移出元素时,二级菜单则会隐藏。
有以下三种实现方法
1、首先我们想到的是通过js的鼠标事件来进行处理,那么我们应该先明确一下几个事件的基本概念。
-
mouseenter:当定点设备(通常指鼠标)移动到元素上时就会触发 mouseenter 事件
-
mouseleave:指点设备(通常是鼠标)的指针移出某个元素时,会触发mouseleave事件。
-
mouseout 和 mouseover和以上两个事件的作用相似,那么他们的区别在于什么地方呢?
借助于MDN上的描述: 当指针离开元素及其所有后代时,会触发mouseleave,而当指针离开元素或离开元素的后代(即使指针仍在元素内)时,会触发mouseout
–> 通过定时器+mouseenter、mouseLeave事件来实现二级菜单的显示与隐藏,定时器的作用是解决频繁触发mouseenter事件,造成页面抖动bug,实现代码如下:
//设置一个定时器 让用户在菜单停留150ms 系统再触发反馈 防止界面抖动
let timer = null //mouseenter事件
timer = setTimeout(function() {
$('#二级菜单').show() //显示二级菜单(要执行的操作)
}, 150);//mouseLeave事件
$('#二级菜单').hide() //隐藏二级菜单(要执行的操作)
clearTimeout(timer);
2、可以通过css的hover属性,切换二级菜单的display属性(block、hidden)
3、防抖与节流
- 基本概念
①防抖: 指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
②节流:连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
个人理解,防抖就是LOL中的回城,节流就是英雄大招 0.0
->适用场景如下:在前端开发中,我们有时要绑定一些持续触发的函数,例如mouseenter、mouseover、resize、scroll、oninput
等,但有些时候我们并不希望在事件持续触发的过程中那么频繁地去执行函数,这个时候我们可以用到防抖与节流。 - 应用
1)防抖:
<input type="text">
<script>const dom = document.querySelector('input')dom.oninput = function() {
console.log(this.value);}
</script>
->此时我们可以做一下防抖,当我们连续输入多个值,只打印最后一个值。
<input type="text">
<script>const dom = document.querySelector('input')dom.oninput = debounce(fn, 500)//防抖函数function debounce(fn, delay) {
let timer = null//返回一个函数,oninput事件函数return function () {
//借助闭包,访问外部函数的变量 timerif (timer !== null) {
clearTimeout(timer)}timer = setTimeout(() => {
console.log(this); //指向input//call改变fn函数的this指向,由window 指向 inputfn.call(this) }, delay)}}//业务逻辑函数function fn() {
console.log(this.value);}
</script>
此时控制台的输出如下
2)节流
<input type="text">
<script>const dom = document.querySelector('input')dom.oninput = throttle(fn,500)//节流函数function throttle(fn, delay) {
let timerreturn function () {
if(!timer) {
timer = setTimeout(() => {
timer = nullfn.call(this) }, delay)}}}//业务逻辑函数function fn() {
console.log(this.value);}
</script>