zoukankan      html  css  js  c++  java
  • bootstrap treeview树形菜单 动态扩展 连数据库

    二话不说,先来看效果图:

    呃呃,虽然不是很美观......不过功能实现就好啦~

    数据库模型是这样的:

    我做了什么工作呢?

    简单解释一下,就是通过查数据库,把上面的数据查出来,每一行数据封装成为一个节点,然后拼成一颗树,最后显示在前台。注意:这里的数据是可以动态扩展的。

    字段解释:nodeId就是节点的id。pid是 parentId也就是父亲的id,表示该节点是哪个节点的子节点。type=1代表功能,type=0代表菜单。level代表该节点在树的第几层。

    OK,大家应该迫不及待想要知道具体实现了.....

    满足大家,先来看前端代码:

      1 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
      2 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
      3 <html>
      4 <head>
      5 <%
      6     String server_path = request.getContextPath();
      7 %>
      8 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      9 </head>
     10 <!-- bootstrap-treeview 导包-->
     11 <link rel="stylesheet" type="text/css" href="<%=server_path %>/bootstrap-3.3.7-dist/css/bootstrap.css" >
     12 <link rel="stylesheet" type="text/css" href="<%=server_path %>/bootstrap-3.3.7-dist/treeview/bootstrap-treeview.css">
     13 <script type="text/javascript" src="<%=server_path %>/bootstrap-3.3.7-dist/treeview/jquery.js"></script>
     14 <script type="text/javascript" src="<%=server_path %>/bootstrap-3.3.7-dist/treeview/bootstrap-treeview.js"></script>
     15 
     16 <script type="text/javascript">
     17 //选中/取消父节点时选中/取消所有子节点
     18 function getChildNodeIdArr(node) {
     19     var ts = [];
     20     if (node.nodes) {
     21         for (x in node.nodes) {
     22             ts.push(node.nodes[x].nodeId);
     23             if (node.nodes[x].nodes) {
     24                 var getNodeDieDai = getChildNodeIdArr(node.nodes[x]);
     25                 for (j in getNodeDieDai) {
     26                     ts.push(getNodeDieDai[j]);
     27                 }
     28             }
     29         }
     30     } else {
     31         ts.push(node.nodeId);
     32     }
     33     return ts;
     34 }
     35 //选中所有子节点时选中父节点
     36 function setParentNodeCheck(node) {
     37     var parentNode = $("#tree").treeview("getNode", node.parentId);
     38     if (parentNode.nodes) {
     39         var checkedCount = 0;
     40         for (x in parentNode.nodes) {
     41             if (parentNode.nodes[x].state.checked) {
     42                 checkedCount ++;
     43             } else {
     44                 break;
     45             }
     46         }
     47         if (checkedCount === parentNode.nodes.length) {
     48             $("#tree").treeview("checkNode", parentNode.nodeId);
     49             setParentNodeCheck(parentNode);
     50         }
     51     }
     52 }
     53 
     54 $(function () {
     55     $.ajax({
     56         type: "Post",
     57         url: '<%= server_path%>/resource/menu',  
     58         dataType: "json",
     59         success: function (result) {
     60             $('#tree').treeview({
     61                 data: result.list,         // 数据源
     62                 showCheckbox: true,   //是否显示复选框
     63                 highlightSelected: true,    //是否高亮选中
     64                 multiSelect: true,    //多选
     65                 levels : 2,
     66                 enableLinks : true,//必须在节点属性给出href属性
     67                 color: "#010A0E",
     68                 onNodeChecked : function (event,node) {
     69                     var selectNodes = getChildNodeIdArr(node); //获取所有子节点
     70                     if (selectNodes) { //子节点不为空,则选中所有子节点
     71                         $('#tree').treeview('checkNode', [selectNodes, { silent: true }]);
     72                     }
     73                 },
     74                 onNodeUnchecked : function(event, node) { //取消选中节点
     75                     var selectNodes = getChildNodeIdArr(node); //获取所有子节点
     76                     if (selectNodes) { //子节点不为空,则取消选中所有子节点
     77                         $('#tree').treeview('uncheckNode', [selectNodes, { silent: true }]);
     78                     }
     79                 },
     80                 
     81                 onNodeExpanded : function(event, data) {
     82                         
     83                 },
     84                     
     85                 onNodeSelected: function (event, data) {
     86                     //alert(data.nodeId);
     87                 }
     88                     
     89             });
     90         },
     91         error: function () {
     92             alert("菜单加载失败!")
     93         }
     94     });
     95 })
     96 </script>
     97 </head>
     98 <body>
     99 <div id="tree" class="col-sm-2"></div>
    100 </body>
    101 </html>

      你没有看错,就是这么一个文件就搞定啦。。。

    对了,导包不要导错了。没有这些包可以去浏览器下载bootstrap treeview包。下不来可来找我要。

    okok,然后看神奇的后台代码:

     1 @Controller
     2 @RequestMapping("/resource")
     3 public class ResourceController extends BaseController{
     4 
     5     @RequestMapping("menu")
     6     public void getMenu(HttpServletRequest request,HttpServletResponse response) throws Exception{
     7         json.setResult("no");
     8         Node tree = getTreeJson();//获得一棵树模型的数据
     9         //json.setData(tree);
    10         json.setList(tree.getNodes());
    11         json.setResult("ok");
    12         response.getWriter().println(mapper.writeValueAsString(json));//把json数据写回前台
    13     }
    14     
    15 
    16      public Node getTreeJson() {
    17          List<Resource> reslist = resourceService.loadAll();//从数据库获取所有资源
    18          List<Node> nodes = new ArrayList<Node>();//把所有资源转换成树模型的节点集合,此容器用于保存所有节点
    19          for(Resource res : reslist){
    20              Node node = new Node();
    21              node.setHref(res.getUrl());
    22              node.setIcon(res.getIcon());
    23              node.setNodeId(res.getNodeId());
    24              node.setPid(res.getPid());
    25              node.setText(res.getName());
    26              nodes.add(node);//添加到节点容器
    27          }
    28          Node tree = new Node();//重要插件,创建一个树模型
    29          Node mt = tree.createTree(nodes);//Node类里面包含了一个创建树的方法。这个方法就是通过节点的信息(nodes)来构建一颗多叉树manytree->mt。
    30          //System.out.println(tree.iteratorTree(mt));
    31          return mt;
    32      }
    33     
    34 }

    以上代码,就是负责把数据库的数据取出来,封装成对应的节点,根据节点创建一颗树,然后封装成json数据传到前台,就那么简单。

    看不懂不要紧,上面用了springmvc框架做控制器,如果你没有这环境,又想做测试,你完全可以用其他控制器,servlet都行,只要能把json数据传回前台就行。当然,上面还用了一些组件,这也不要紧,最重要的不就是红色部分的代码嘛,请睁大眼睛:

      1 import java.util.ArrayList;
      2 import java.util.List;
      3 /**
      4  * 树形节点模型
      5  * @author chenht
      6  *
      7  */
      8 public class Node {
      9     public Node() { 
     10         this.nodes = new ArrayList<Node>();
     11     }
     12     public Node(String nodeId,String pId) {
     13         this.nodeId = nodeId;
     14         this.pid = pId;
     15         this.nodes = new ArrayList<Node>();
     16     }
     17     /**
     18      * 生成一个节点
     19      * @param nodeId
     20      * @param pId
     21      * @param text
     22      * @param icon
     23      * @param href
     24      */
     25     public Node(String nodeId, String pId, String text, String icon, String href) {
     26         super();
     27         this.nodeId = nodeId;
     28         this.pid = pId;
     29         this.text = text;
     30         this.icon = icon;
     31         this.href = href;
     32         this.nodes = new ArrayList<Node>();
     33     }
     34 
     35     private String nodeId;    //树的节点Id,区别于数据库中保存的数据Id。
     36     private String pid;
     37     private String text;   //节点名称
     38     private String icon;
     39     private String href;   //点击节点触发的链接
     40     private List<Node> nodes;    //子节点,可以用递归的方法读取
     41     
     42     public String getNodeId() {
     43         return nodeId;
     44     }
     45     public void setNodeId(String nodeId) {
     46         this.nodeId = nodeId;
     47     }
     48     
     49     public String getPid() {
     50         return pid;
     51     }
     52     public void setPid(String pid) {
     53         this.pid = pid;
     54     }
     55 
     56     public String getText() {
     57         return text;
     58     }
     59     public void setText(String text) {
     60         this.text = text;
     61     }
     62     
     63     public String getIcon() {
     64         return icon;
     65     }
     66     public void setIcon(String icon) {
     67         this.icon = icon;
     68     }
     69     
     70     public String getHref() {
     71         return href;
     72     }
     73     public void setHref(String href) {
     74         this.href = href;
     75     }
     76     
     77     public List<Node> getNodes() {
     78         return nodes;
     79     }
     80     public void setNodes(List<Node> nodes) {
     81         this.nodes = nodes;
     82     }
     83     
     84     /**
     85      * 生成一颗多叉树,根节点为root
     86      * @param Nodes 生成多叉树的节点集合
     87      * @return root
     88      */
     89     public Node createTree(List<Node> Nodes) {
     90         if (Nodes == null || Nodes.size() < 0)
     91             return null;
     92         Node root = new Node("root","0");//根节点自定义,但是要和pid对应好
     93         // 将所有节点添加到多叉树中
     94         for (Node node : Nodes) {
     95             if (node.getPid().equals("0") || node.getPid().equals("root")) {//根节点自定义,但是要和pid对应好
     96                 // 向根添加一个节点
     97                 root.getNodes().add(node);
     98             } else {
     99                 addChild(root, node);
    100             }
    101         }
    102         return root;
    103     }
    104 
    105     /**
    106      * 向指定多叉树节点添加子节点
    107      * @param Node 多叉树节点
    108      * @param child 节点
    109      */
    110     public void addChild(Node Node, Node child) {
    111         for (Node item : Node.getNodes()) {
    112             if (item.getNodeId().equals(child.getPid())) {
    113                 // 找到对应的父亲
    114                 item.getNodes().add(child);
    115                 break;
    116             } else {
    117                 if (item.getNodes() != null && item.getNodes().size() > 0) {
    118                     addChild(item, child);
    119                 }
    120             }
    121         }
    122     }
    123 
    124     /**
    125      * 遍历多叉树
    126      * @param Node 多叉树节点
    127      * @return
    128      */
    129     public String iteratorTree(Node Node) {
    130         StringBuilder buffer = new StringBuilder();
    131         buffer.append("
    ");
    132         if (Node != null) {
    133             for (Node index : Node.getNodes()) {
    134                 buffer.append(index.getNodeId() + ",");
    135                 if (index.getNodes() != null && index.getNodes().size() > 0) {
    136                     buffer.append(iteratorTree(index));
    137                 }
    138             }
    139         }
    140         buffer.append("
    ");
    141         return buffer.toString();
    142     }
    143 
    144     public static void main(String[] args) {
    145         List<Node> nodes = new ArrayList<Node>();
    146         nodes.add(new Node("系统管理", "0"));
    147         nodes.add(new Node("角色管理", "系统管理"));
    148         nodes.add(new Node("资源管理", "系统管理"));
    149         nodes.add(new Node("用户管理", "系统管理"));
    150         nodes.add(new Node("添加用户", "用户管理"));
    151         nodes.add(new Node("修改用户", "用户管理"));
    152         nodes.add(new Node("机票管理", "系统管理"));
    153 
    154         Node tree = new Node();
    155         Node mt = tree.createTree(nodes);
    156         System.out.println(tree.iteratorTree(mt));
    157     }
    158 
    159      
    160 }

     欧克欧克,代码就是那么多,一个文件搞定,有人可能不相信。好吧,火狐浏览器下看传回来的参数是这样的:

    现在总该相信了吧?到此,基本介绍完啦,惊不惊喜,开不开心?好吧,本文主要的特点是可动态扩展树中的节点,而且与数据库的数据一一对应上。前台用bootstrap的treeview

    做展示,想必你看本文之前,已看过不少关于treeview的文章了吧。ps:红色字体是本文重点。

  • 相关阅读:
    Oracle Hint的用法
    利用flashback transaction query新特性进行事务撤销
    存储的一些基本概念(HBA,LUN)
    SAN和NAS
    SAN (Storage Attached Network),即存储区域网络
    深入浅出谈存储之NAS是什么
    对于NAS,IP SAN以及iSCSCI SAN存储的一些认识和理解
    Oracle的体系结构
    利用360免费wifi搭建局域网让他人访问Oracle数据库
    杭电ACM id:3783
  • 原文地址:https://www.cnblogs.com/chenhtblog/p/8342534.html
Copyright © 2011-2022 走看看