• 无限级菜单简单的设计


    策略:数据库就一张表,前端查询出所有的可显示的菜单,在前端进行循环展示。

    1,数据库表的设计

    CREATE TABLE sys_menu (
      id     INT         NOT NULL  AUTO_INCREMENT,
      name   VARCHAR(64) NOT NULL,
      url    VARCHAR(255),
      pid    INT         NOT NULL  DEFAULT 0,
      isLeaf TINYINT     NOT NULL  DEFAULT 1
      COMMENT '0表示不是叶子,1表示是叶子',
      status TINYINT     NOT NULL  DEFAULT 1
      COMMENT '0表示禁用,1表示启用',
      seq    TINYINT     NOT NULL  DEFAULT 0
      COMMENT '同级中的顺序,0-n,从上到下',
      PRIMARY KEY (id)
    );

    把菜单当作一个多叉树,root节点为虚拟节点,id为0。第一层节点表示一级菜单,以此类推。其中,isLeaf表示该菜单是不是叶子节点。

    简单的填充数据如下所示:

    2,查询所有菜单的接口(略,简单的sql查询)

    需要过滤status=0,也就是禁用的菜单。

    3,前端展示

    3.1 html代码和css样式

    body中就是如下简单的代码

    <body>
    <ul class="Menue">
    </ul>
    </body>

    css样式(从网上随便找的)

    <style type="text/css">
            a {
                text-decoration: none;
            }
    
            ul, li {
                list-style: none;
                margin: 0;
                padding: 0;
            }
    
            /*定义菜单*/
    
            .Menue li {
                background: #111;
                color: #fff;
                height: 30px;
                line-height: 30px;
                position: relative;
                float: left;
                margin-right: 5px;
                width: 100px;
                text-align: center;
                font-family: Arial, Helvetica, sans-serif;
            }
    
            .Menue li a {
                color: #fff;
                font-size: 14px;
                display: block;
            }
    
            /*下拉菜单样式*/
    
            ul.sub_menu {
                position: absolute;
                width: 100px;
                display: none;
                z-index: 999;
            }
    
            .Menue li ul.sub_menu li {
                background: none;
                color: #555;
                font-size: 12px;
                border-bottom: 1px #333 solid;
                position: relative;
                width: 100px;
                height: 30px;
            }
    
            .Menue li ul.sub_menu li.last {
                border-bottom: none;
            }
    
            /*js会对最后一个li添加该class,去掉border-bottom效果*/
    
            .Menue li ul.sub_menu li a {
                background: #222;
                color: #888;
                display: block;
                height: 30px;
            }
    
            .Menue li ul.sub_menu li a:hover, .Menue li ul.sub_menu li a.now {
                background: #f90;
                color: #fff;
            }
    
            .Menue li.now, .Menue li.current {
                background: #f60;
                color: #fff;
            }
    
            /*如果有下拉菜单添加的class*/
    
            .hasmenu {
                background: url(arrow.png) no-repeat right;
                padding-right: 15px;
            }
    
            /*主导航箭头向下*/
    
            .Menue li a.hasmenu {
                background: url(arrow.png) no-repeat right;
                padding-right: 15px;
                background-position: right -30px;
            }
    
            /*下拉菜单箭头向右*/
    
            .Menue li ul.sub_menu li a.hasmenu {
                background: #222 url(arrow.png) no-repeat right top;
            }
    
            .Menue li ul.sub_menu li a.hasmenu:hover {
                background: #f90 url(arrow.png) no-repeat right top;
                color: #fff;
            }
    
        </style>

    3.2 jquery ajax获取所有的菜单数据

    $.ajax({
            type: "GET",
            url: "<%=request.getContextPath()%>/menu/getMenus.do",
            dataType: "json",
            success: function (result) {
                if (result.status > 0) {
                    //获取到菜单数据,进行展示
                    //1,展示顶级菜单
                    var list = result.body;
                    var i;
                    for (i = 0; i < list.length; i++) {
                        //console.log(typeof list[i].url == 'undefined');//如果url不存在,则为undefined,应该用typeof判断
                    }
                    //$(".Menue").html("");
                    $(".Menue").html(showFirstLevelMenu(list));
                    console.log(showFirstLevelMenu(list))
                    //在菜单全部显示后,增加hover件事
                    addHover();
                } else {
                    alert(result.message);
                }
            },
            error: function () {
                alert("服务器故障,请刷新或稍后重试!");
            }
        })

    当获取到数据后,将数据拼装成节点html数据,设置到class=Menu的ul中。然后对动态添加的html代码段加上hover事件

    $(".Menue").html(showFirstLevelMenu(list));
    //在菜单全部显示后,增加hover事件
    addHover();

    3.3 递归拼接

    使用递归调用实现拼接子菜单

    function showFirstLevelMenu(list) {
            //class = Menu_li
            //遍历list找到
            var menu = "";
            var subList = new Array();
            var i;
            for (i = 0; i < list.length; i++) {
                if (list[i].pid == 0) {
                    subList.push(list[i]);
                }
            }
            subList.sort(function (a, b) {
                return a.seq - b.seq;//从小到大排序
            });
            alert(subList.length)
            for (i = 0; i < subList.length; i++) {
                menu += '<li class="Menue_li">' + showSubMenu(list, subList[i]) + '</li>';
            }
            return menu;
        }
    
        function showSubMenu(list, menuInfo) {
            //class = sub_menu
            var menu = '<a href="#">' + menuInfo.name + '</a>';
            if (menuInfo.isLeaf == 0) {//有子菜单
                var subList = new Array();
                var i;
                for (i = 0; i < list.length; i++) {
                    if (list[i].pid == menuInfo.id) {
                        subList.push(list[i]);
                    }
                }
                if (subList.length != 0) {
                    subList.sort(function (a, b) {
                        return a.seq - b.seq;//从小到大排序
                    });
                    menu += '<ul class="sub_menu">';
                    for (i = 0; i < subList.length; i++) {
                        menu += '<li>' + showSubMenu(list, subList[i]) + '</li>';
                    }
                    menu += '</ul>';
                }
            }
            return menu;
        }

    3.4 hover事件(网上粘贴的)

    function addHover() {
    
            //为导航设置默认高亮 与本菜单无关
    
            $("ul.Menue li.Menue_li:eq(0)").addClass("current")
    
            /*jquery menu 开始*/
    
            //为子菜单的最后一个li添加样式,适合为li添加下划线时去除最后一个的下划线
    
            $(".sub_menu").find("li:last-child").addClass("last")
    
            //遍历全部li,判断是否包含子菜单,如果包含则为其添加箭头指示状态
    
            $(".Menue li").each(function () {
    
                if ($(this).find("ul").length != 0) {
                    $(this).find("a:first").addClass("hasmenu")
                }
    
            })
    
    
            //
    
            $(".Menue li").hover(function () {
    
                $(this).addClass("now");
    
                var menu = $(this);
    
                menu.find("ul.sub_menu:first").show();
    
            }, function () {
    
                $(this).removeClass("now");
    
                $(this).find("ul.sub_menu:first").hide();
    
            });
    
    
            var submenu = $(".sub_menu").find(".sub_menu")
    
            submenu.css({left: "100px", top: "0px"})
    
            $(".sub_menu li").hover(function () {
    
                $(this).find("a:first").addClass("now")
    
                $(this).find("ul:first").show();
    
            }, function () {
    
                $(this).find("a:first").removeClass("now")
    
                $(this).find("ul:first").hide()
    
            });
    
            /*jquery menu 结束*/
    
        }

    3.5 最终页面显示结果

    =====>>=====>>

  • 相关阅读:
    前端Vue项目——购物车页面
    vue组件通信传值——Vuex
    django+uwsgi+nginx 导出excel超时问题
    前端Vue项目——登录页面实现
    前端Vue项目——课程详情页面实现
    基于DFA算法、RegExp对象和vee-validate实现前端敏感词过滤
    python的小数据池
    VeeValidate——vue2.0表单验证插件
    前端Vue项目——首页/课程页面开发及Axios请求
    服务配置中心
  • 原文地址:https://www.cnblogs.com/ljdblog/p/7594548.html
Copyright © 2020-2023  润新知