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、创建好之后的效果

   

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

时间: 2024-08-06 04:48:58

JavaScript处理数据完成左侧二级菜单的搭建的相关文章

用jquery插件写一个小米官网左侧二级菜单

知识点:静态布局思路,jquery动态布局,代码格式规范,jquery插件调用, 鼠标滑动二级菜单构建. html代码: <div id="Tz_banner"> <ul> <li class="firstLi">手机 电话卡 <div class="info"> <ul> <li><a class="title" href="#"

用一些简易的标签写一个美丽说左侧二级菜单

知识点:html标签(div,ul,a),css样式属性(浮动,定位),布局思想,js基础,逻辑思维. 对前端感兴趣或者正在学习web前端的小伙伴可以来前端群:189394454,每天会有干货分享,以及学习路线方法! html代码: <div id="Menu"> <h3>全部商品</h3> <ul> <li> <a href="#">上衣</a><a href="#

vue.js 左侧二级菜单显示与隐藏切换的实例代码

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>vue点击切换显示隐藏</title> <script src="js/same/vue.js"></script> <style type="text/css"> *{ padding: 0; margin: 0; fo

根据权限动态生成二级菜单

数据库models设计: from django.db import models """ 一级菜单 """ class Menu(models.Model): title = models.CharField(max_length=32, unique=True) icon = models.CharField(max_length=32, verbose_name="图标", null=True, blank=True)

Javascript实现简单的下拉二级菜单

在线演示;http://jsfiddle.net/Web_Code/ThhbG/embedded/result/ <span style="font-size:14px;"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <

jquery实现后台系统左侧菜单的点击展开/收缩二级菜单效果

html: <div class="col-sm-3 col-md-2 sidebar"> <div class="totalt"><a>系统管理系统</a></div> <ul class="menu"> <li class="title"> <a class="item item1"><span cla

一级菜单 二级菜单的联动

1.页面代码:单个集合循环生成一级和二级菜单 /* <c:forEach var="m" items="${list}" >                              <c:if test="${m.mb.father eq '-1' }">                                   <input type="checkbox" name="me

RABC权限控制(二级菜单实现)

目前大部分系统由于用户体验,基本上菜单不会做的很深,以二级菜单为例,做了一个简单的权限控制实现,可精确到按钮级别(基于django),下面具体看看实现 1.表结构的设计 无论开发什么都需要先梳理清楚需求,然后再考虑表结构,这里先来说说大致的表结构组成,注意,我的权限控制是通过url做的,所以控制的核心就在于控制url 表字段介绍设计如下: 权限表 url # 权限 title #权限的标题,左侧展示,代表的功能(因为不可能展示url吧) menu # 所属的一级菜单,外键关联一级菜单 paren

动态生成二级菜单

现在越来越多的用到二级甚至多级菜单,前台菜单的显示,手动指定也越来越不能满足要求,所以,动态生成菜单是必须的 思路 + 示例代码(以二级菜单为例) 先取出一级菜单内容值,接下来遍历一级菜单,将其id当做本次检索的parentid,将与之对应的二级菜单值获取到, 并加入到当前数组中(后台) 二层循环,当获取一个值时,检查其对于的二级菜单项是否有数据,有的话,则输出来,没有则跳过(前台) 以PHP后台为例 $res = mysql_query('*** where parentid = 0');