在工作之余,自己研究了jquery Eayui tree (樹控件)遠程數據的加載,網上實現的方法很多,內容寫的也比較簡單,對初學者很難理解。因此本文主要是針對初學者做了比較詳細的實現教程。
在繼續下文的學習中,首先你要自己對EasyUI的樹控件有所了解(查看教程)。我們看一下樹控件怎么使用Javascript加載在頁面定義好的json數據。定義一個<ul id='home-tree'></ul>標簽,並定義好樹數據json。
var tree_data = [{
id : 1,
text: '人員管理',
state: 'closed',
children: [{
id : 11,
text: '人員設置',
attributes : {
url : '${path}/menuTree/index/success'
}
},{
id : 12,
text: '角色設置',
attributes : {
url : '${path}/menuTree/index/error'
}
}]
},{
id:2,
text: '菜單管理',
state: 'closed',
children : [{
id:21,
text: '菜單配置',
attributes : {
url : '${path}/menuTree/index/error'
}
}]
}];
$(function(){
$('#home-tree').tree({
data: tree_data
});
});
運行效果:
就這樣,一個菜單樹出來了。做這樣的展示有什么用呢?這樣做為了我們遠程加載樹控件數據做了准備,為我們怎么在數據庫中定義樹控件數據表做了准備。
在tree_data變量中,是樹控件需要的數據。其中用到的屬性有:
- id:節點ID,對加載遠程數據很重要。
- text: 顯示節點文本。也就是菜單的標題
- state:節點狀態,'open' 或 'closed',默認:'open'。如果為'closed'的時候,將不自動展開該節點。
- attributes: 被添加到節點的自定義屬性。
- children: 一個節點數組聲明了若干節點。
- url: 檢索遠程數據的URL地址。
這些屬性中哪些是要記錄到數據庫表中,經過分析id,text,state,url這些屬性是有數據的。其中父節點的數據包含id,text,state;子節點的數據包含id,text,url。細心的網友會發現在tree_data中還有children和attributes這兩個屬性,這兩個屬性怎么辦?因為這兩個屬性不直接存儲數據,或者說這兩個屬性的數據都是來自id,text,state,url這些屬性中,這兩個屬性會在定義實體中說明,那么我們是否存在數據庫中存儲id,text,state,url這些屬性的值就可以了呢?這樣不行的,子節點是屬於哪個父節點還需要關聯到父節點的id,因此還需要存儲一個子節點對應的父節點pid.建立如下樹菜單表:
Field | Type | Comment | |
id | varchar(255) NOT NULL | ||
pid | varchar(255) NULL | 父節點id | |
text | varchar(255) NULL | ||
status | varchar(255) NULL | ||
url | varchar(255) NULL |
插入如下數據:
數據庫建立好后,建立實體:
package com.wh.bean; import java.io.Serializable; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Description: 樹實體 * @author hong.wei * Date 2016年9月8日 上午11:19:43 * @version V1.0 */ public class MenuTree implements Serializable{ /** * */ private static final long serialVersionUID = 2604341300672377675L; private String id; private String pId; //父節點id private String text; private String state; private String url; private Map<String, Object> attributes = new HashMap<String, Object>(); // 添加到節點的自定義屬性 private List<MenuTree> children; //子節點數據 /* ... ... get set 方法 */ }
在實體中多了個Map<String, Object> attributes 和一個List<MenuTree> children,這兩個就是tree_data數據中attributes和children這兩個屬性,這兩個屬性具體的使用看后面的代碼。
數據庫數據有了,實體也有了,下面寫具體的業務邏輯。把jsp頁面的樹控件數據改為調用遠程服務器地址,完整代碼:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>主頁面</title> <%@include file="common/common.jsp" %> </head> <script type="text/javascript"> $(function(){ $('#home-tree').tree({ url : '${path}/menuTree/selectMenuTrees', }); }); </script> <body> <ul id='home-tree'></ul> </body> </html>
$('#home-tree').tree({})中的 url : '${path}/menuTree/selectMenuTrees',就是請求遠程服務器地址獲得樹控件所需的數據。后台代碼:
package com.wh.controller; import java.util.ArrayList; import java.util.List; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import com.wh.bean.MenuTree; import com.wh.service.IMenuTreeService; import com.wh.util.TreeNoteUtil; /** * Description: 菜單樹控制層 * @author hong.wei * Date 2016年9月7日 下午2:47:50 * @version V1.0 */ @Controller @RequestMapping("menuTree") public class MenuTreeController { private static final Logger LOGGER = LoggerFactory.getLogger(MenuTreeController.class); @Resource private IMenuTreeService service; @RequestMapping(value = "selectMenuTrees") @ResponseBody public Object selectMenuTrees(HttpServletRequest request, HttpServletResponse response){ //用於接收數據庫查詢到的數據 List<MenuTree> list = new ArrayList<MenuTree>(); //用於把接收到的數據改造成EasyUI tree認識的數據格式 List<MenuTree> menuTrees = new ArrayList<MenuTree>(); try { //后台接收到的數據 list = service.selectMenuTrees(new MenuTree()); //TreeNoteUtil為工具類,用於改造數據 menuTrees = TreeNoteUtil.getFatherNode(list); } catch (Exception e) { LOGGER.error("MenuTreeController.selectMenuTrees() error:" + e); } return menuTrees; } }
代碼中只需要關心 public Object selectMenuTrees(){}這個方法中的內容就可以了,這個為主要的具體業務邏輯。在這個方法中調用了TreeNoteUtil.getFatherNode()方法。
TreeNoteUtil用遞歸方法把后台接收到的數據轉換成樹控件認識的json數據。TreeNoteUtil類代碼:
package com.wh.util; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; import com.wh.bean.MenuTree; /** * Description: 遞歸獲取樹節點集合 * @author hong.wei * Date 2016年9月7日 下午6:10:41 * @version V1.0 */ public class TreeNoteUtil { /** * 獲取父節點菜單 * @param treesList 所有樹菜單集合 * @return */ public final static List<MenuTree> getFatherNode(List<MenuTree> treesList){ List<MenuTree> newTrees = new ArrayList<MenuTree>(); for (MenuTree mt : treesList) { if (StringUtils.isEmpty(mt.getpId())) {//如果pId為空,則該節點為父節點 //遞歸獲取父節點下的子節點 mt.setChildren(getChildrenNode(mt.getId(), treesList)); newTrees.add(mt); } } return newTrees; } /** * 遞歸獲取子節點下的子節點 * @param pId 父節點的ID * @param treesList 所有菜單樹集合 * @return */ private final static List<MenuTree> getChildrenNode(String pId, List<MenuTree> treesList){ List<MenuTree> newTrees = new ArrayList<MenuTree>(); for (MenuTree mt : treesList) { if (StringUtils.isEmpty(mt.getpId())) continue; if(mt.getpId().equals(pId)){ //遞歸獲取子節點下的子節點,即設置樹控件中的children mt.setChildren(getChildrenNode(mt.getId(), treesList)); //設置樹控件attributes屬性的數據 Map<String, Object> map = new HashMap<String, Object>(); map.put("url", mt.getUrl()); mt.setAttributes(map); newTrees.add(mt); } } return newTrees; } }
這樣就OK了,運行程序,出來的效果跟開頭使用使用Javascript加載在頁面定義好的json數據一樣,這里不再上圖。
整個應用的架構是應用SpingMVC+mybatis架構。