首页 > 其他分享 >菜单栏-JS防抖

菜单栏-JS防抖

时间:2022-12-19 13:45:10浏览次数:49  
标签:box 防抖 menu list timer 菜单栏 let JS box2

一、 需求

写一个菜单栏,能够实现:

  • 鼠标悬浮时展开子菜单
  • 鼠标离开时折叠子菜单

二、简单实现+问题

  • 简单绑定 mouseover mouseleave 实现折叠和展开。
  • 容易抽风,表现为,鼠标反复横跳几次,就会反复折叠展开

简单实现代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>防抖测试</title>
    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    <style>
        #box, #box2{
            position: relative;
            width: 46px;
            background-color: rgb(250, 250, 250);
            padding: 5px 20px;
            text-align: center;
        }
        .row2{
            margin: 250px 0;
        }
        .menu{
            user-select: none;
        }
        .menu-list, .menu-list2{
            position: absolute;
            top: 26px;
            left: 0;
            width: 86px;
            background-color: rgb(235, 235, 235);
        }
        a{
            display: block;
            text-decoration: none;
            color: #000;
            padding: 2px 0;
        }
        a:hover{
            background-color: aliceblue;
        }
    </style>
</head>
<body>

    <div class="row2">
        <div id="box2">
            <div class="menu">菜单1</div>
        </div>
    </div>

    <script>
        $(()=>{
            let data = [
                {'label': "资料", 'link': '/info/123'},
                {'label': "收藏", 'link': '/fav/123'},
                {'label': "历史", 'link': '/history/123'},
            ]
            let listStr = ''
            for(let itm of data){
                listStr += `<a href="${itm.link}">${itm.label}</a>`
            }
            let listBlock2 = `<div hidden class="menu-list2">${listStr}</div>`
            $('#box2').append(listBlock2)

            // 简单的直接绑定事件
            $("#box2,#box2").mouseover(()=>{
                $('#box2 .menu-list2').slideDown()
            })

            $("#box2").mouseleave(()=>{
                $('#box2 .menu-list2').slideUp(300)
            })
        })
    </script>
    
</body>
</html>

效果演示:

三、防抖

  防抖,简单解释就是将动作延迟一定时间再执行,如果在该时间内重复触发事件,那么延迟的时间会重置,只有真正达到延迟时间,才会执行回调函数。
  在这里,是将子菜单的折叠进行防抖,鼠标移开目标后,子菜单延迟一段时间折叠;若在这段时间内鼠标重新移入,那取消执行折叠,如果移入又移出,重置延迟时间,循环上述过程。
  这样就避免了鼠标不小心横跳,造成的抽风式效果。

关键代码:

  • .menu 对应 “菜单”
  • .menu-list 对应子菜单
let timer = ''
$("#box .menu").mouseover(()=>{
    clearTimeout(timer)
    $('#box .menu-list').mouseover(()=>{
        clearTimeout(timer)
        $('#box .menu-list').slideDown()
    })
    $('#box .menu-list').slideDown()
})

$("#box .menu, #box .menu-list").mouseleave(()=>{
    clearTimeout(timer)
    timer = setTimeout(()=>{
        $('#box .menu-list').slideUp(300)
    }, 300)
})

效果:

四、完整代码

  • 包含简单实现和加了防抖后的部分
  • 可以直接复制到一个新的HTML文件,在浏览器打开查看效果(联网,需要加载 jquery
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>防抖测试</title>
    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    <style>
        #box, #box2{
            position: relative;
            width: 46px;
            background-color: rgb(250, 250, 250);
            padding: 5px 20px;
            text-align: center;
        }
        .row2{
            margin: 250px 0;
        }
        .menu{
            user-select: none;
        }
        .menu-list, .menu-list2{
            position: absolute;
            top: 26px;
            left: 0;
            width: 86px;
            background-color: rgb(235, 235, 235);
        }
        a{
            display: block;
            text-decoration: none;
            color: #000;
            padding: 2px 0;
        }
        a:hover{
            background-color: aliceblue;
        }
    </style>
</head>
<body>

	<!-- 防抖,它加了防抖! -->
    <div id="box">
        <div class="menu">菜单2</div>
    </div>

	<!-- 简单实现部分 -->
    <div class="row2">
        <div id="box2">
            <div class="menu">菜单1</div>
        </div>
    </div>

    <script>
        $(()=>{
        	// 填充的子菜单数据
            let data = [
                {'label': "资料", 'link': '/info/xxx'},
                {'label': "收藏", 'link': '/fav/xxx'},
                {'label': "历史", 'link': '/history/xxx'},
            ]

            let listStr = ''
            for(let itm of data){
                listStr += `<a href="${itm.link}">${itm.label}</a>`
            }
            let listBlock = `<div hidden class="menu-list">${listStr}</div>`
            let listBlock2 = `<div hidden class="menu-list2">${listStr}</div>`
            $('#box').append(listBlock)
            $('#box2').append(listBlock2)
			// 防抖部分时间绑定
            let timer = ''
            $("#box .menu").mouseover(()=>{
                clearTimeout(timer)
                $('#box .menu-list').mouseover(()=>{
                    clearTimeout(timer)
                    $('#box .menu-list').slideDown()
                })
                $('#box .menu-list').slideDown()
            })
            $("#box .menu, #box .menu-list").mouseleave(()=>{
                clearTimeout(timer)
                timer = setTimeout(()=>{
                    $('#box .menu-list').slideUp(300)
                }, 300)
            })

            // 简单的直接绑定事件
            $("#box2,#box2").mouseover(()=>{
                $('#box2 .menu-list2').slideDown()
            })
            $("#box2").mouseleave(()=>{
                $('#box2 .menu-list2').slideUp(300)
            })
        })
    </script>
</body>
</html>

标签:box,防抖,menu,list,timer,菜单栏,let,JS,box2
From: https://www.cnblogs.com/pxoxq/p/16991935.html

相关文章

  • Node.js
    下载安装node.jshttps://nodejs.org/zh-cn/download/npm安装yarn安装npminstall-gyarn切换淘宝镜像yarnconfigsetregistryhttps://registry.npm.taobao.orgy......
  • When to use next() and return next() in Node.js
    Somepeoplealwayswritereturnnext()istoensurethattheexecutionstopsaftertriggeringthecallback.Ifyoudon'tdoit,yourisktriggeringthecallback......
  • <%@ include file=""%>与<jsp:include page=""/>区别
         通常当应用程序中所有的页面的某些部分(例如标题、页脚和导航栏)都相同的时候,我们就可以考虑用include。具体在哪些时候用<%@includefile=""%>,哪些时候用<jsp:in......
  • vuejs实现文件下载的三种方式
    第一种方式是前端创建超链接,通过a标签的链接向后端服务发get请求,接收后端的文件流,非常简单:<a:href='"/路径"'>下载模板</a>另一种情况是创建div标签,动态创建a标签:<div......
  • Jsp底层实现原理
    JSP底层原理分析在WEB-INF目录外创建一个index.jsp文件将项目部署成功之后启动服务器,浏览器访问该jsp页面,在服务器启动页面可以看到CATALINE_BASE这个信息org.......
  • JS节点操作 之 Node和Element的区别
    简介Node对象DOM的标准规范中提供了Node对象,该对象主要提供了用于解析DOM节点树结构的属性和方法。Node对象是解析DOM节点树结构的主要入口,Node对象提供的属性和方法,可......
  • Intel的Mac,Threejs在Chrome性能下降严重
    参考地址:https://github.com/mrdoob/three.js/issues/23821Threejs在新版中,已经将WebGLRenderer默认使用webgl2。可以使用WebGL1Renderer退回webgl1,性能问题会得到解决。......
  • 原生JS的节点操作 与 JQuey的节点操作 对比
    前言公司要求不使用JQuery,而使用原生JS。作为一个用惯了JQuery的人来说,用原生JS的节点操作无疑是很难用的。这篇随笔,目的是总结对比JQuery与原生JS的各种节点操作的区别......
  • JSON
    作者:david_zhang@sh【转载时请以超链接形式标明文章】https://www.cnblogs.com/david-zhang-index/p/16991324.html序列化:既java对象转json,StringobjJson=JSON.toJSO......
  • 第一百一十五篇: JS集合引用类型Map
    好家伙,本篇为《JS高级程序设计》第六章“集合引用类型”学习笔记 1.MapECMAScript6以前,在JavaScript中实现“键/值”式存储可以使用object来方便高效地完成,也就是使用对......