zoukankan      html  css  js  c++  java
  • JavaScript处理数据完成左侧二级菜单的搭建

      我们在项目中应用的后台管理框架基本上都是大同小异,左侧是一个二级菜单,点击选中的菜单,右侧对应的页面展示。我把前端页面封装数据的过程整理了一下,虽然不一定适合所有的管理页面,仅作为案例来参考,只是希望大家能明白实现原理就好。

      左侧的菜单的搭建:

       1、首先将我们需要应用的菜单导入数据库。

        下面的截图是我导入的数据:

        

        根据我的业务需求,我需要四个父菜单,所以我将他们的pid字段都设置为0,子菜单的pid字段对应的是父菜单的id,这很重要。url字段就是点击该菜单时,右侧页面显示的地址路径。status状态字段代表当前菜单的状态是否可用,我这里设置的0为可用,1为不可用,稍后会看到。order_num字段这里暂时用不到。

        2、封装一个构造函数来读取并创建二级菜单

        为了不使这个案例太过于繁琐,在不考虑这个构造函数的灵活性的情况下,我尽量的减少代码量。假设只是针对本案例,封装的函数如下:  

    复制代码
    function MenuTree(id,url){
        this.id = id;
        this.url = url;
        this.$Div = null;
        this.$curA = null;
        this.initTree();    
    }
    
    MenuTree.prototype.initTree = function(){
        var self = this; 
        //左侧菜单的容器,根据元素的id来定义
        this.$Div = $("#"+this.id);
        if(this.$Div.length == 0){
            alert("菜单初始化外容器失败");
            return;
        }
        //点击方法的代理,点击这个容器时会使用this.treeClick定义的方法来代理
        this.$Div.click($.proxy(this.treeClick,this));
        //向设置好的菜单地址发送请求
        $.post(this.url,function(data){
            self.createTreeMenu(data.list);
        },"json")    
    }
    MenuTree.prototype.createTreeMenu = function(list){
        //若没有读取到数据,或者数据长度为0,容器会显示暂无菜单
        if(!list||list.length == 0){
            this.$Div.html("暂无菜单");
            return;
        }
        //声明一个空对象,用来存放创建的菜单信息
        var rootNodes = {};
        var len = list.length;
        var node = null;
        var curNodeId="";
        for(var i=0;i<len;i++){
            node = list[i];
            //当读取到的菜单status为1时,代表菜单不可用,跳过
            if(node.status=='1') continue;
            var id = node.id;
            var name = node.name;
            var url = node.url;
            var pid = node.pid;
            //当本条数据pid为0时,创建这条数据为父菜单
            if(pid == "0"){
                rootNodes[id] = $("<div class='leftTreeMenu hasChildren'><leftMenuTitle>"+name+"</leftMenuTitle></div>");
                continue;
            }
            //子菜单的pid是父菜单的id,所以这里的rootNodes[pid]就是上面的rootNodes[id]
            var $pnode = rootNodes[pid];
            //子菜单创建后要把id和url作为自定义属性添加到元素上面,后面会用到
            var $a = $("<leftTreeNode id='leftTreeLink_"+id+"'>"+name+"</leftTreeNode>").attr("id",id).attr("url",url);
            $pnode.append($a);
            //这里略过不提,下一篇文章讲
            if(fromURI && (url==fromURI)){
                this.$curA = $a.addClass("currentA");
                $pnode.addClass("currentMenu").removeClass("hideChildren");
                myBar.freshTag(id,name,url);
            }
        }
        var df = document.createDocumentFragment();
        for(key in rootNodes){
            //appendChild是原生js的用法
            //[0]的目的是将jq的对象转换成dom对象
            df.appendChild(rootNodes[key][0]);
        }
        (this.$Div)[0].appendChild(df);
    }
    
    MenuTree.prototype.treeClick = function(e){
        //click事件,会用到dom和jq的转换
        var target = e.target;
        var nodeName = target.nodeName;
        //如果点击的是父菜单,就通过切换class名字来展示和隐藏子菜单
        if(nodeName == "LEFTMENUTITLE"){
            $(target).parent().switchClass("hideChildren");
            return;
        }
        //如果点击的是子菜单,就处理子菜单的数据    
        if(nodeName == "LEFTTREENODE"){
            this.freshTag($(target));
        }
    }
    
    MenuTree.prototype.changeCurNode = function($e){
        //如果点击的与选中的是同一个,就return
        if(this.$curA == $e) return;
        //如果this.$curA存在,就将以前的类名currentA移除并子菜单隐藏
        if(this.$curA){
            this.$curA.removeClass("currentA").parent().removeClass("currentMenu");
        }
        //刚刚点击的添加类名currentA并显示子菜单
        this.$curA = $e.addClass("currentA");
        $e.parent().addClass("currentMenu").removeClass("hideChildren");
    }
    
    MenuTree.prototype.freshTag = function($e){
        //处理点击的元素
        this.changeCurNode($e);
        //将绑定在元素上的url取出
        var url = $e.attr("url");
        if(url.indexOf("http")==0 ){
            window.open(url);
            return;    
        }
        //这个会在下一篇文章再讲,这里是创建右侧mybar和url页面的显示信息
        myBar.freshTag($e.attr("id"),$e.html(),url);
    } 
    复制代码

        3、JSP页面的调用

        JSP页面很简单,创建一个左侧容器id为“leftTree”,然后:

    var leftTree = new MenuTree("leftTree","<c:url value='/menu/getMenuTree'/>");

        我说明一下,这篇文章只是讲解左侧菜单的读取和创建,至于点击显示对应页面准备在下一篇文章介绍。

        4、后台的处理过程    

    复制代码
    package cn.wangze.controller;
    
    import java.util.List;
    
    import javax.annotation.Resource;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.SessionAttributes;
    
    import cn.wangze.service.SysCacheService;
    import cn.wangze.service.SysMenuService;
    
    import cn.wangze.domain.SysMenu;
    //import cn.wangze.service.SysMenuService;
    //import cn.wangze.utils.AuthUtils;
    
    @Controller
    @RequestMapping("/menu")
    @SessionAttributes("sysUser") 
    public class SysMenuController01 extends BaseController{
        Log log = LogFactory.getLog(getClass());
        
        //将菜单的service注入控制器里面
        @Resource
        private SysMenuService<SysMenu> sysMenuService;
        //若菜单固定的话,我们可以将数据放到缓存中,这样不用每次都从数据库请求
        @Autowired
        private SysCacheService sysCacheService;
        
        @RequestMapping(value = "/{pagePath}/{pageName}")
        public String goMenuPage(@PathVariable String pagePath, @PathVariable String pageName,HttpServletRequest request) {
            setFromURI(request);
            return "/" + pagePath + "/" + pageName;
        }
        
        @RequestMapping(value = "/getMenuTree")
        public void getMenu(HttpServletResponse response,HttpSession session) {
            //调用sysCacheService的queryMenuList方法来取数据
            List<SysMenu> list = sysCacheService.queryMenuList();
            log.debug("总菜单:" + list);
            if (list == null) return;
            //可参照我前面发的博客文章,封装的返回数据的方法,在BaseController里面
            sendJsonList(list, response);
        }
    }
    复制代码

        Service和Domain层还有Mapper层的代码我就不发了,就是查询的操作,因为没有涉及到角色权限的控制,所以没有多大的难度。

      5、创建好之后的效果

       

      下一篇文章我们讲解点击子菜单,右侧显示对应地址的过程。

  • 相关阅读:
    SQLite数据库框架ORMLite与GreenDao的简单比较
    Spring Web MVC中的页面缓存支持 ——跟我学SpringMVC系列
    admin嵌套在spring mvc项目里,菜单栏点击新连接每次都会重置
    Spring MVC视图层:thymeleaf vs. JSP
    使用Spring标签库
    SpringMVC中Controller跳转到另一个Controller方法
    有趣iOS开展
    Java日期的格式String类型GMT,GST换算成日期Date种类
    javascript之Style物
    Tair LDB基于Prefixkey中期范围内查找性能优化项目总结
  • 原文地址:https://www.cnblogs.com/shitaotao/p/7648237.html
Copyright © 2011-2022 走看看