今天要說說的內容是,使用zTree實現一個異步加載樹,因爲在某些情況下,樹形式的菜單或者數據,可能會有成百上千個,一次性加載出來是十分的慢的,非常影響用戶使用友好度。所以非常有必要學習一下異步加載,zTree是jQuery的一個樹形的插件,現在可以下碼雲上下載源代碼。這是下載鏈接: https://gitee.com/zTree/zTree_v3 使用需要將其css和js文件夾放入你的工程下
這是解壓完成後的文件夾。
也需要引入jQuery,因爲需要初始化zTree。
前端頁面代碼如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="js/ztree/zTreeStyle/zTreeStyle.css">//引入ztree css文件
<link rel="stylesheet" href="js/ztree/demo.css">//這個引入不引入都可以,引入看起來會美觀一些,會有個容器包裹住樹
</head>
<body>
<div>
<ul id="treeDemo" class="ztree"></ul>//這個就是我們要顯示的樹形菜單,也就是要綁定的暗元素
</div>
<script type="text/javascript" src="js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="js/ztree/jquery.ztree.core.js"></script>//ztree核心文件
<script>
//ztree需要的setting參數 view data async 我僅僅使用到了這三個,還有其他參數,請參閱ztree的api
var setting = {
view: {
selectedMulti: false,//禁止多選節點 只能同時選中一個節點
expandSpeed:""//設置節點展開的速度
},
data:{
//設置數據接收的格式,其實是有兩種數據接收的格式,但是個人感覺這種好用,也不會有亂的感覺。前端ztree接收的json對象是這樣的
{
"code":0,
"count":10,
"data":[
{"area":1000,
"description":"土壤肥沃",
"id":1,"name":"黑龍江省",
"pid":"-1",
"population":500000
},
{"area":1000,
"description":"土壤肥沃",
"id":2,"name":"遼寧省",
"pid":"-1",
"population":400000
}],
"msg":"ok"
}
上面的是簡單的,簡單的在於是有pid和id進行標註id爲父,pid指定那個id爲父。
複雜的呢,就是在data裏面進行嵌套如下所示:
{ "area":400,
"description":"二龍湖",
"population":55555
child:[{ "area":400,
"description":"二龍湖1",
"population":55555},{ "area":400,
"description":"二龍湖2",
"population":55555},child[{此處繼續進行嵌套},{此處繼續進行嵌套}]]
}
所以個人感覺還是使用簡單模式,後端數據處理的時候也方便.
simpleData:{
enable:true,//是否啓用簡單數據模式
idKey:"id",//指定id屬性名字是id
pIdKey:"pid",//指定pid屬性是pid
rootPId:"-1"//指定root(所有節點的根節點)節點的id是-1,這個可以任意設置 0 或者 其他
}
},
async:{//異步操作設置
enable:true,//是否開啓異步
url:"/demo/provinceCity/getProvinceCityById.do",//請求數據的路徑
contentType: "application/json",//ajax請求參數的類型
autoParam:["id"],//發送數據的參數爲id
type:"post",//發送的方式爲post請求
}
};
$.fn.zTree.init($("#treeDemo"), setting);//初始化ztree,總共需要三個參數,第一個參數是綁定的標籤,第二個是setting參數,第三個是data數據參數。我是連根節點也進行異步請求了,所以沒設置data參數,你也可以設置爲null,他也會默認將根節點進行異步請求。
</script>
</body>
</html>
接下來是數據庫表結構:
接下來介紹後端代碼,配置文件已經介紹過,看我以前的文章。
bean代碼:
public class ProvinceCityBean {//get set方法就不貼了
/**
* id.
*/
private Long id;
/**
* 省省市名字.
*/
private String name;
/**
* 父id.
*/
private String pid;
/**
* 面積.
*/
private Long area;
/**
* 人口數量.
*/
private Long population;
/**
* 描述.
*/
private String description;
/**
* 是否爲父節點.
*/
private Boolean isParent;}
controller代碼:
/**
* 根據id獲取其下所有的子節點.
* @param provinceCityBean 條件.
* @return 子節點集合.
*/
@RequestMapping("/getProvinceCityById")
@ResponseBody
public Object getProvinceCityById(@RequestBody ProvinceCityBean provinceCityBean) {
return provinceCityService.getProvinceCityById(provinceCityBean);
}
service代碼:
接口:
/**
* 根據id獲取其下所有的子節點.
* @param provinceCityBean 條件.
* @return 子節點集合.
*/
List<ProvinceCityBean> getProvinceCityById(ProvinceCityBean provinceCityBean);
實現類:
@Override
public List<ProvinceCityBean> getProvinceCityById(ProvinceCityBean provinceCityBean) {
if (provinceCityBean.getId() == null) {
//如果傳過來的id爲空那麼就默認異步加載根節點
provinceCityBean.setId(-1L);
}
//下面是爲了給前端傳遞數據時,傳遞一個他是否有子節點的標誌位,如果有子節點,則可以繼續展開,否則不能。
List<ProvinceCityBean> lists = provinceCityDao.getProvinceCityById(provinceCityBean);
for (ProvinceCityBean item : lists) {
if (hasChild(item)) {
item.setIsParent(true);
} else {
item.setIsParent(false);
}
}
return lists;
}
haschild方法:
接口:
/**
* 當前節點是否還有子節點.
* @param provinceCityBean 當前節點.
* @return 是否存在子節點.
*/
Boolean hasChild(ProvinceCityBean provinceCityBean);
實現類:
/**{@inheritDoc} */
@Override
public Boolean hasChild(ProvinceCityBean provinceCityBean) {
Integer count = provinceCityDao.hasChild(provinceCityBean);
if (count > 0) {
return true;
}
return false;
}
dao:
dao:
/**
* 當前節點是否還有子節點.
* @param provinceCityBean 當前節點.
* @return 子節點數量.
*/
Integer hasChild(ProvinceCityBean provinceCityBean);
/**
* 根據id獲取其下所有的子節點.
* @param provinceCityBean 條件.
* @return 子節點集合.
*/
List<ProvinceCityBean> getProvinceCityById(ProvinceCityBean provinceCityBean);
mapping映射:
<select id="hasChild" parameterType="com.doart.bean.ProvinceCityBean" resultType="Integer">
select count(*)
from province_city
where p_id = #{id} and del_flag = 0
</select>
<select id="getProvinceCityById" parameterType="com.doart.bean.ProvinceCityBean" resultType="com.doart.bean.ProvinceCityBean">
select id, p_id, name
from province_city
where p_id = #{id} and del_flag = 0
</select>
完事,補充說明一下:在bean那裏不應該在provincecity裏面添加isparent屬性,應該在寫一個ztree的類,ztree包含isparent,icon路徑等屬性,然後讓javabean繼承ztree就可以啦。還有前端返回的數據一定要告訴後端,這個節點是否爲父節點,下面是否還存在子節點,也就是給前端傳遞的標誌位isparent,如果沒有傳遞這個數據,前端只能顯示根節點這一層,這是我血的教訓啊,大家一定不要犯這個錯誤.
今天的博客到此爲止啦,大家一起加油吧.