ZTree

zTree

zTree是中国人写的非常强大的一个”树”,下面介绍一种非常经典的多级目录勾选树。

zTree

生成一个多级目录的勾选树:

基于角色模块分配,两个表是多对多的关系。

把相关的js,css引入进来

在要用zTree的地方引进这些样式跟js

1
2
3
4
5
<link rel="stylesheet" href="${ctx}/components/zTree/css/zTreeStyle/zTreeStyle.css" type="text/css" />
<script type="text/javascript" src="${ctx}/components/zTree/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="${ctx}/components/zTree/js/jquery.ztree.core-3.5.min.js"></script>
<script type="text/javascript" src="${ctx}/components/zTree/js/jquery.ztree.excheck-3.5.min.js"></script>

进入到模块分配页面

1
2
3
4
5
6
7
8
9
10
11
/**
 * 进入到模块分配页面
 */
public String tomodule() throws Exception {
  //1.根据角色id,得到角色对象
  Role role = roleService.get(Role.class, model.getId());
  //2.将角色对象放入值栈中
  super.push(role);
  //3.跳页面
  return "tomodule";
}

配置页面

1
2
3
4
5
6
7
8
9
10
11
12
<script>
var zTreeObj;
var setting = {
  check : {
    enable : true
  },
  data : {
    simpleData : {
      enable : true
    }
  }
};

使用ajax从服务器端接受数据生成对应的树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$(function(){
  $.ajax({
    type:"GET",
    url:"${ctx}/sysadmin/roleAction_loadJSONTreeNodes.action?id=${id}",
    dataType:"json",
    success:initzTree
  });
});
function initzTree(data){
  //1.初始化树
  zTreeObj = $.fn.zTree.init($("#jkTree"), setting, data);
  //2.展开树上的所有结点
  zTreeObj.expandAll(true);
}

服务器传过来的数据

为了加载zTree树上的结点,zTree树上结点的数据结构:

1
2
    [{"id":"编号","pId":"父结点的编号","name":"结点名称","checked":"true|false"},
     {"id":"编号","pId":"父结点的编号","name":"结点名称","checked":"true|false"}]

  • 使用什么技术来生成这样json串
    • JSON-lib FastJSON GSON 自己手动拼接
    • 其实自己拼接是最方便的因为可以,实现在拼接的时候能够实现自己需要的业务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public String loadJSONTreeNodes() throws Exception {
  //1.根据角色 id加载角色对象
  Role obj = roleService.get(Role.class, model.getId());
  //2.对象导航,得到当前这个角色所具有的模块列表
  Set<Module> moduleSet = obj.getModules();
  //3.加载数据库中所有的模块列表
  List<Module> moduleList = moduleService.find("from Module where state=1", Module.class, null);
  //4.拼接JSON串
  StringBuilder sb = new StringBuilder();
  sb.append("[");
  int size=moduleList.size();//得到集合中元素的个数
  for(Module module :moduleList){
    size--;
    //遍历出每个模块
    sb.append("{\"id\":\"").append(module.getId());
    sb.append("\",\"pId\":\"").append(module.getParentId());
    sb.append("\",\"name\":\"").append(module.getName());
    sb.append("\",\"checked\":\"");
    if(moduleSet.contains(module)){
      //当前用户具有的这个模块
      sb.append("true");
    }else{
      sb.append("false");
    }
    sb.append("\"}");
    if(size>0){
      sb.append(","); //当size=0时,说明集合中没有其它元素要遍历了,此时的元素是最后一个元素,后面不能添加逗号了
    }
  }
  sb.append("]");
  //输出
  HttpServletResponse response = ServletActionContext.getResponse();
  //设置编码
  response.setContentType("application/json;charset=UTF-8");//json数据的mime类型:application/json
  response.setHeader("Cache-Control", "no-cache");//设置响应消息头,没有缓存
  response.getWriter().write(sb.toString());//向客户端输出
  return NONE;
}
  • 使FastJson转换Json,使用的时候在所有的工具中速度最快(效率没有上面的快,因为需要创建很多对象,跟遍历集合)

    • list—->数组
    • map—–>键值对
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      List<Map<String,object>> list = new ArrayList<Map<String,object>>();
      for(Module module : moduleList){
      Map<String,object> maps=new Map<String,object>();
      maps.put("id",module.getId());
      maps.put("pId",module.getParentId());
      maps.put("name",module.getName());
      boolean flag= false;
      if(moduleSet.contains(module)){
      flag=true;
      }
      maps.put("ckecked",flag);
      list.add(maps);
      }
      String jsonStr = Json.toJSONString(list);
  • FastJson中

    • 对象转String用toJSONString
    • 字符串转Json用Parse

根据服务器端的数据获取所被选择的节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function submitCheckedNodes() {
  var nodes = new Array();
  nodes = zTreeObj.getCheckedNodes(true);   //取得选中的结点
  var str = "";
  for (i = 0; i < nodes.length; i++) {
    if (str != "") {
      str += ",";
    }
    str += nodes[i].id;
  }
  //把选中的节点id拼成一个字符串传到action
  $('#moduleIds').val(str);
}
</script>
//把选中的节点id拼成一个字符串传到action
<input type="hidden" id="moduleIds" name="moduleIds" value="" />
//zTree树
<div>
    <ul id="jkTree" class="ztree"></ul>  
</div>

实现模块分配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 实现模块分配
* <input type="hidden" name="id" value="${id}"/>
<input type="hidden" id="moduleIds" name="moduleIds" value="" />
*/
public String module() throws Exception {
  //1.根据角色id,得到角色对象
  Role role = roleService.get(Role.class, model.getId());
  //2.切割模块的id字符串
  String []mids = moduleIds.split(",");//模块id的数组
  //创建一个模块列表的集合
  Set<Module> moduleSet = new HashSet<Module>();
  //3.遍历每个模块的id
  for(String id :mids){
    Module m = moduleService.get(Module.class, id);//加载出模块对象
    moduleSet.add(m);//将加载出来的模块对象,放入模块列表中
  }
  //3.设置角色与模块的关系
  role.setModules(moduleSet);
  //4.保存角色与模块的关系
  roleService.saveOrUpdate(role);
  //5.跳页面
  return "alist";
}
  • 每一个数据类型都有自己的mime的文件类型:
    • json是:application/json,Tomcat会在web.xml中校验mime类型
    • 所以需要设置编码: response.setContentType("application/json;charset=UTF-8");
    • 设置响应消息头,没有缓存 response.setHeader(Cache-Control,)

注:

  • Ztree可以通过setting的callback属性添加事件

    1
    2
    3
    4
    var setting = {
    callback:{
         onClick:function(){}
    }}
  • Ztree树的容器class必须是ztree

  • Ztree树容器是<li>

  • 也可以接受一个text数值在转成json


zTree的加载过程:

张冲 wechat
欢迎扫一扫上面的微信关注我,一起交流!
坚持原创技术分享,您的支持将鼓励我继续创,点击打赏!