使用 zTree 异步加载
使用场景
可能需要展示类别很多,如果采用直接加载的方式,需要展示的数据量过大,交互十分不友好。所以采用 zTree 异步加载数据。
demo 环境
SpringBoot 1.5.9.RELEASE , 使用 jsp
war
org.springframework.boot
spring-boot-starter-parent
1.5.9.RELEASE
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-tomcat
org.apache.tomcat
tomcat-servlet-api
8.5.28
provided
javax.servlet
javax.servlet-api
org.apache.tomcat.embed
tomcat-embed-jasper
javax.servlet
jstl
导入 zTree 所需的 css 和 js ,导入到 resources/static 下
jsp 代码
Created by IntelliJ IDEA.
User: lvhaosir
Date: /12/12
Time: 8:52
To change this template use File | Settings | File Templates.
--%>
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
index
var basePath = '';
Ztree异步加载使用例子
var setting = {
async: {
enable: true,
url: basePath + "ztree/asyncGetNodes",
autoParam:["id"],
dataFilter: filter
},
data:{
simpleData:{
enable: true,
idKey:'id',
pIdKey:'pid',
rootPId: 0
}
},
view:{
showIcon: false
}
};
$(document).ready(function(){
initZTree();
});
function filter(treeId, parentNode, childNodes) {
return childNodes;
}
//初始化树
function initZTree(){
$.ajax({
url:basePath + "ztree/getNodes",
type:"post",
dataType: "json",
success: function(data){
console.log(data);
var zTreeObj = $.fn.zTree.init($("#zTree"),setting, data);
//让第一个父节点展开
var rootNode_0 = zTreeObj.getNodeByParam('pid',0,null);
zTreeObj.expandNode(rootNode_0, true, false, false, false);
},
error: function(){
}
});
}
Java 代码
model
package cn.lvhaosir.ztree.model;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @Author: lvhaosir
* @Date: /12/12 9:09
* @Version 1.0
*/
@Data
@AllArgsConstructor
public class Node {
private String id;
/**
* 父节点 id
*/
private String pid;
private String name;
/**
* 是否展开
*/
private String open;
/**
* 是否为父节点(下面是否还有分类)
*/
private String isParent;
}
controller
PageController
package cn.lvhaosir.ztree.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Author: lvhaosir
* @Date: /12/12 8:50
* @Version 1.0
*/
@Controller
@RequestMapping("/page")
public class PageController {
/**
* 跳转界面
* @return
*/
@RequestMapping(value="/{filename}")
public String toPage(@PathVariable(value="filename") String filename){
System.out.println("filename:"+filename);
return filename;
}
/**
* 跳转界面
* @return
*/
@RequestMapping(value="/{folder}/{filename}")
public String toPage(@PathVariable(value="folder") String folder,@PathVariable(value="filename") String filename){
System.out.println("folder:"+folder +" filename:"+filename);
return folder+"/"+filename;
}
}
ZtreeController
package cn.lvhaosir.ztree.controller;
import cn.lvhaosir.ztree.model.Node;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: lvhaosir
* @Date: /12/12 9:10
* @Version 1.0
*/
@Controller
@RequestMapping("/ztree")
public class ZtreeController {
@RequestMapping("/getNodes")
@ResponseBody
public List getNodes() {
List nodeList = new ArrayList();
nodeList.add(new Node("1","0","一级菜单1","false","true"));
nodeList.add(new Node("10","1","二级菜单1","false","true"));
nodeList.add(new Node("11","1","二级菜单2","false","true"));
nodeList.add(new Node("12","1","二级菜单3","false","true"));
nodeList.add(new Node("2","0","一级菜单2","false","true"));
nodeList.add(new Node("20","2","二级菜单21","false","true"));
nodeList.add(new Node("21","2","二级菜单22","false","true"));
nodeList.add(new Node("22","2","二级菜单23","false","true"));
return nodeList;
}
@RequestMapping("/asyncGetNodes")
@ResponseBody
public List asyncGetNodes(String id) throws InterruptedException {
List nodeList = new ArrayList();
if("10".equals(id)){
nodeList.add(new Node("100",id,"三级菜单1","false","true"));
nodeList.add(new Node("101",id,"三级菜单2","false","false"));
} else if ("11".equals(id)) {
nodeList.add(new Node("102",id,"三级菜单21","false","false"));
nodeList.add(new Node("103",id,"三级菜单22","false","true"));
} else if ("12".equals(id)) {
nodeList.add(new Node("104",id,"三级菜单31","false","false"));
nodeList.add(new Node("105",id,"三级菜单32","false","false"));
}
Thread.sleep(2000);
return nodeList;
}
}
菜单树就能正确展示出来了。
实际使用场景
在我们实际的场景应该是,有一个根据菜单父 id 查询菜单的接口,页面首先进去加载顶级菜单,一般也就是 pid=0 的菜单,然后点击节点,传递该节点的 id 异步向后台查询子菜单来进行异步加载。