bootstrap treetable 树形网格,动态扩展,连数据库

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

 

1、先来看写死的:

展开前~~

展开后~~

 怎么实现呢?

先new 一个jsp文件,导入几个包,编写html代码,编写js代码,一个文件搞定!

 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 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 6 <title>Insert title here</title>
 7 <script type="text/javascript" src="../bootstrap-3.3.7-dist/treeview/jquery.js"></script>
 8 <script type="text/javascript" src="../js/jquery.treetable.js"></script>
 9 <link rel="stylesheet" type="text/css" href="../css/jquery.treetable.css">
10 <link rel="stylesheet" type="text/css" href="../css/jquery.treetable.theme.default.css">
11 <script type="text/javascript">
12 $(document).ready(function(){
13     $("#treeTable").treetable({  
14         expandable : true,
15         initialState:"expanded",
16         //expandable : true
17         clickableNodeNames:true,//点击节点名称也打开子节点.
18         indent : 30//每个分支缩进的像素数。
19     });
20 });
21 </script>
22 </head>
23 <body>
24     <div>
25     <table id="treeTable" style="width:800px">  
26         <tr>  
27              <td>名字</td> 
28              <td>URL</td> 
29              <td>操作<td>
30          </tr>  
31          <tr data-tt-id="a">  
32              <td>a</td> 
33              <td>a.jsp</td> 
34              <td><button>edit</button> <td>
35          </tr>  
36          <tr data-tt-id="a1" data-tt-parent-id="a">  
37              <td>a1</td>
38              <td>a1.jsp</td>  
39              <td><button>edit</button> <td>
40          </tr>  
41          <tr data-tt-id="b">  
42              <td>b</td>  
43              <td>b.jsp</td> 
44              <td><button>edit</button> <td>
45          </tr>  
46          <tr data-tt-id="b1" data-tt-parent-id="b">  
47              <td>b1</td>  
48              <td>b1.jsp</td> 
49               <td><button>edit</button> <td>
50          </tr>  
51     </table>  
52     </div>
53 </body>
54 </html>

把上面代码拷回去试试?记得导treetable的包。

 

 

2、有了上面的基础,再来看连数据库的,可动态扩展(推荐),但是相对麻烦一点。

效果图:

数据库模型是这样的:

字段解释:nodeId就是节点的id。pid是 parentId也就是父亲的id(注意:最根的节点的pid会和代码耦合,或做好约定——代码总要根据什么字符来找到最根节点),表示该节点是哪个节点的子节点。type=1代表功能,type=0代表菜单。level代表该节点在树的第几层。

我做了什么工作呢?

简单解释一下,就是通过查数据库,把上面的数据查出来,每一行数据封装成为一个节点,然后拼成一颗树,然后对树进行“中序遍历”,按“中序遍历“的顺序把每一个节点添加到list,最后显示在前台(有点绕,下面解释为什么这样做。因为是多叉树,中序遍历我打了引号)。注意:这里的数据是可以动态扩展的。

数据库查出来的数据本来就是一个list,我把这个list的数据封装成为一个节点,然后拼成一颗树,然后又把这颗树按中序的遍历顺序转化成了list。

看似多余,其实这是由于treetable这个插件构建树的时候是根据html的table里面定义的tr来构建的,具体可观察上面写死的那个例子。而它对tr定义的顺序也有要求(有兴趣可在自己机器上调换一下tr的顺序,看看效果)。

在这个前提下,试想:传会前台的数据要怎么解析?传回来的数据毫无疑问是json数据,是用list结构的还是tree结构的?

其实都可以。如果是tree结构的(可见我另外一个例子:http://www.cnblogs.com/chenhtblog/p/8342534.html),前台一样需要对这一棵树进行“中序遍历“,按这个顺序把每一个节点生成一个tr。这里我是在后台处理了业务逻辑,传回来的是“中序遍历“后的list。

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 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 6 <title>Insert title here</title>
 7 <%
 8     String server_path = request.getContextPath();
 9 %>
10 <script type="text/javascript" src="../bootstrap-3.3.7-dist/treeview/jquery.js"></script>
11 <script type="text/javascript" src="../js/jquery.treetable.js"></script>
12 <link rel="stylesheet" type="text/css" href="../css/jquery.treetable.css">
13 <link rel="stylesheet" type="text/css" href="../css/jquery.treetable.theme.default.css">
14 <script type="text/javascript">
15 $(document).ready(function(){
16     $.ajax({
17         "type" : 'post',
18         "url" : '<%= server_path%>/resource/reslist',
19         "dataType" : "json",
20         "success" : function(data) {
21             $.each(data.data, function(idx, obj) {
22                 $("#treeTable").append("<tr data-tt-id=\"" + obj.nodeId + "\" data-tt-parent-id=\"" + obj.pid + "\"><td>" + obj.text + "</td><td>" + obj.href + "</td><td><button id=\"" + obj.nodeId + "\">编辑</button><button id=\"" + obj.nodeId + "\">删除</button></td></tr>");
23             });
24             $("#treeTable").treetable({  
25                 expandable : true,
26                 initialState:"expanded",
27                 //expandable : true
28                 clickableNodeNames:true,//点击节点名称也打开子节点.
29                 indent : 30//每个分支缩进的像素数。
30             });
31         }
32     });
33     
34 });
35 </script>
36 </head>
37 <body>
38     <table id="treeTable" style="width:800px">  
39         <tr>  
40              <td>名字</td> 
41              <td>URL</td> 
42              <td>操作</td>
43          </tr>  
44     </table>  
45 
46 </body>
47 </html>

注意:上面用了ajax的异步请求,要把$("#treeTable").treetable();方法写在success域里面,因为要重新生成table,必须要先有数据,然后才能生成!!!

控制器(springMVC)代码:

@RequestMapping("reslist")
    public void getReslist(HttpServletRequest request,HttpServletResponse response) throws Exception{
        json.setResult("no");//返回前台的json数据
        Node tree = getTreeJson();//获得树形结构的json数据
        Node n = tree.zxPraseTree(tree);//把树形结构数据按中序遍历顺序,加入list
        List<Node> reslist = n.getNodes();//获得上面的list
        List<Node> list = new ArrayList<Node>();
        for(Node node : reslist) {//去掉null节点
            if(null != node) {
                if(node.getNodeId() != null) {
                    list.add(node);
                }
            }
        }
        json.setData(list);//设置,返回到前台
        json.setResult("ok");
        response.getWriter().println(mapper.writeValueAsString(json));
    }

     public Node getTreeJson() {
         List<Resource> reslist = resourceService.loadAll();//从数据库加载所有数据,得到list
         List<Node> nodes = new ArrayList<Node>();
         for(Resource res : reslist){
             Node node = new Node();
             node.setHref(res.getUrl());
             node.setIcon(res.getIcon());
             node.setNodeId(res.getNodeId());
             node.setPid(res.getPid());
             node.setText(res.getName());
             nodes.add(node);
         }
         Node tree = new Node();
         Node mt = tree.createTree(nodes);//把list转化成tree
         System.out.println(tree.iteratorTree(mt));//遍历打印
         return mt;
     }

提供一个工具类:

  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 NodeTree
 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");
 93         // 将所有节点添加到多叉树中
 94         for (Node node : Nodes) {
 95             if (node.getPid().equals("0") || node.getPid().equals("root")) {
 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     
145     /**
146      * 遍历多叉树
147      * @param Node 多叉树节点
148      * @return
149      */
150     List<Node> node = new ArrayList<Node>();
151     public Node zxPraseTree(Node Node) {
152         if (Node != null) {
153             for (Node index : Node.getNodes()) {
154                 node.add(index);
155                 if (index.getNodes() != null && index.getNodes().size() > 0) {
156                     node.add(zxPraseTree(index));
157                 }
158             }
159         }
160         //buffer.append("\n");
161         Node n = new Node();
162         n.setNodes(node);
163         return n;
164     }
165 
166     public static void main(String[] args) {
167         List<Node> nodes = new ArrayList<Node>();
168         nodes.add(new Node("系统管理", "0"));
169         nodes.add(new Node("角色管理", "系统管理"));
170         nodes.add(new Node("资源管理", "系统管理"));
171         nodes.add(new Node("用户管理", "系统管理"));
172         nodes.add(new Node("添加用户", "用户管理"));
173         nodes.add(new Node("修改用户", "用户管理"));
174         nodes.add(new Node("机票管理", "系统管理"));
175 
176         Node tree = new Node();
177         Node mt = tree.createTree(nodes);
178         System.out.println(tree.iteratorTree(mt));
179         Node n = tree.zxPraseTree(mt);
180         List<Node> list = n.getNodes();
181         for(Node node : list) {
182             System.out.println(node.getNodeId());
183         }
184     }
185 
186      
187 }

传回来的数据:

再加上导入bootstrap的包,稍微改一下样式就是第一张图的效果啦~~~

最后再次说明:本例子支持连数据库,动态扩展。但是例子用了springMVC的环境,不可硬搬代码到你机器上去运行哦。主要思路已经写明白了,工具类也给出,已帮各位解决80%难度。主要是要明白每一步做了什么工作,事在人为,根据思路相信你也可以弄出来。说实话网络上太少比较靠谱的例子了。。。

 

posted on 2018-03-05 10:47  愿生命从容  阅读(53819)  评论(3编辑  收藏  举报

导航