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("\n");
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("\n");
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:红色字体是本文重点。

 

posted on 2018-01-25 22:24  愿生命从容  阅读(33234)  评论(10编辑  收藏  举报

导航