自定义横向菜单悬停展示到三级菜单 | 8月更文挑战

693 阅读2分钟

这是我参与8月更文挑战的第30天,活动详情查看:8月更文挑战

样式大概是这样的,用的是jquery+layui的方式,之前有人问过,现在分享一下,如果用vue封装成组件应该也不是很难,看懂原理即可。

一、设置界面样式

<!-- 头部 -->
<div class="layui-header" style="background: none;">
    <div class="layui-logo" id="logotext" style="font-size: 28px;font-family:'黑体';width: 40%;background: none !important" >
        小鲸鱼测试管理系统
    </div>
    <ul class="layui-nav layui-layout-right" lay-filter="admin-side-nav" lay-accordion="true" style="min-width: 45%;margin-right: 14%;text-align: right;">
        <!-- 菜单渲染模板 -->
        <script id="sideNav" type="text/html">
            {{#  layui.each(d, function(index, item){ }}
            <li class="layui-nav-item">
            	<!-- 定义layui自带接口返回跳转页面的地址 -->
                <a href="{{item.menuHref?item.menuHref:'javascript:void(0)'}}" lay-href="{{item.menuUrl}}">
                    <i class="{{item.menuIcon}}"></i>&emsp;
                    <!-- 这里是菜单前面的图片,可以动态判断展示或者接口返回直接用 -->
                    <img src="./assets/images/setIcon.png" class="jsxsjcIcon">
                    <cite class="fs16Cite">{{item.name}}</cite><!-- 一级标题名称 -->
                </a>
                {{# if(item.children&&item.children.length>0){ }}
                <dl class="layui-nav-child">
                    <!-- 第二级菜单 -->
                    {{# layui.each(item.children, function(index, subItem){ }}
                    <dd>
                        <a href="{{ subItem.menuHref }}" title="{{ subItem.name }}" lay-href="{{ subItem.menuUrl }}" data-isRight='{{subItem.children.length}}' class="erRight">
                            <i class="{{subItem.menuIcon}}"></i>&emsp;{{ subItem.name }}
                            {{# if(subItem.children.length > 0){ }}
                                <i class="layui-icon layui-icon-triangle-r"></i>
                            {{# } }} 
                        </a>
                        <!-- 第三级菜单 -->
                        {{# if(subItem.children.length > 0){ }}
                            <dl class="rightChildBox" style="display: none">
                                {{# layui.each(subItem.children, function(index, subTemp){ }}
                                <dd>
                                    <a href="{{ subTemp.menuHref }}" title="{{ subTemp.name }}" lay-href="{{ subTemp.menuUrl }}" class="sanNav">
                                        <i class="{{subTemp.menuIcon}}"></i>&emsp;{{ subTemp.name }}
                                    </a>
                                </dd>
                                {{# }); }}
                            </dl>
                        {{# } }} 
                    </dd>
                    {{# }); }}
                </dl>
                {{# } }}
            </li>
            {{#  }); }}
        </script>
    </ul>
    <ul class="layui-nav layui-layout-right">
        <li class="layui-nav-item layui-hide-xs" lay-unselect>
            <a ew-event="fullScreen" title="全屏"><i class="layui-icon layui-icon-screen-full"></i></a>
        </li>
        <li class="layui-nav-item" lay-unselect style="margin-right: 10px;">
            <a>
                <img src="assets/images/head.png" class="layui-nav-img">
                <cite id="user-name-index">管理员</cite>
            </a>
            <dl class="layui-nav-child">
                <dd lay-unselect>
                    <a id="setInfo">个人信息</a>
                </dd>
                <dd lay-unselect>
                    <a id="setPsw">修改密码</a>
                </dd>
                <hr>
                <dd lay-unselect>
                    <a id="btnLogout">退出</a>
                </dd>
            </dl>
        </li>
    </ul>
</div>

这里页面定义的地方,主要用到layui提供的模板引擎,如果是vue开发就可以直接用template的模板语法写,通过循环的方法吧三级菜单展示出来,如果还有更多级别也可以增加渲染,或者想着用递归的方式写?现在这样循环看起来有点多,不太好复用的样子。

二、定义菜单数据

let menus = [
	{
		"id":"1001",
		"parentId":"-1",
		"children":[],
		"name":"用户管理",
		"menuHref":"#!xjy-userInfo",
		"menuUrl":"/view/userInfo.html",
	},{
		"id":"1002",
		"parentId":"-1",
		"children":[
			{
				"id":"100201",
				"children":[],
				"name":"系统管理",
				"menuHref":"#!xjy-system",
				"menuUrl":"/view/system.html",
			},{
				"id":"100202",
				"children":[
					{
						"id":"10020201",
						"children":[],
						"name":"角色管理",
						"menuHref":"#!xjy-role",
						"menuUrl":"/view/role.html",
					},{
						"id":"10020202",
						"children":[
							{
								"id":"1002020101",
								"children":[],
								"name":"个人账号",
								"menuHref":"#!xjy-userAccount",
								"menuUrl":"/view/userAccount.html",
							},{
								"id":"1002020102",
								"children":[],
								"name":"公用账号",
								"menuHref":"#!xjy-companyAccount",
								"menuUrl":"/view/companyAccount.html",
							}
						],
						"name":"账号管理",
						"menuHref":"#!xjy-account",
						"menuUrl":"/view/account.html",
					}
				]
			}
		]
	}
}]

这里可以是接口返回的数据,我这里写死了,就是一个json数组,里面用children来判断是否有下级,其实还有parentId来判断是否有第一级,我看数据太多了就删掉了。

三、渲染到页面上

laytpl(sideNav.innerHTML).render(menus, function (html) {
    $('*[lay-filter=admin-side-nav]').html(html);
    element.render('nav');
});

laytpl是layui自带的模板引擎,引用定义一下,sideNav是模板引擎。

四、悬停展示二级菜单,悬停二级菜单展示三级菜单,点击并跳转

//三级菜单悬停展示
let isHoverSanNav = false;
let erEl = null;
setTimeout(() => {
    $(".erRight").hover(function() {
        $(this).siblings().show();
    },function() {
        erEl = $(this);
        setTimeout(function() {
            if(!isHoverSanNav) {
                erEl.siblings().hide();
            }
        },100)
    })
    $(".sanNav").hover(function() {
        $(this).parent().parent().show();
        isHoverSanNav = true;
    },function() {
        isHoverSanNav = false;
        $(this).parent().parent().hide();
    })
},1000)

这里是最麻烦的,因为要悬停展示下拉菜单,用到的第一级菜单是layUi自带的,第二级菜单悬停就需要自己写了,定义一个外部变量isHoverSanNav来判断是否展示第三级菜单,并定义一个erEl代表悬停的第二级菜单的dom元素,后面在悬停隐藏的时候再把第三级菜单隐藏掉。

设置setTimeout延时是给点击事件提供事件,因为点击事件是画html的时候用a标签超链接自带的。然后hover第一个方法是悬停展示的内容,第二个方法是设置隐藏div菜单栏的方法,悬停第二级展示第三级菜单。