首页 > 代码库 > EasyUI的功能树之异步树
EasyUI的功能树之异步树
最近几个项目都用到了EasyUI这个Jquery框架,目前感觉起来还是很好使的,展示效果很好,帮助文档什么的资料很多,而且互联网上Easy粉很多,大多数拥护和喜爱EasyUI的粉丝们都愿意在网络平台互相分享学习成果,甚至有专门的社区来讨论使用情况,网址是http://bbs.jeasyuicn.com/,里面的资源模块里有很多都是免费的学习资料,包括视频文档项目源码等,建议初学者去看视频,然后研究一下这个网站(sypro)的实现http://sshe.jeasyuicn.com/,甚至有视频教程教大家怎么实现这个项目。互联网是一个巨人,他博学多才,期待能站在巨人的肩膀上开开眼界,学习到更多的知识技能,对于将来或现在的工作都是一个很大的收获。
本篇博客是对EasyUI中树的实现的总结。如果想要展示一棵树,有很多方式,当然要分析你的需求。如果是展示省市区、学校、部门等大数据的话,建议还是使用异步加载。当然如果只是展示几个几乎不变的菜单项,就可以扁平化的展示你的数据了。
首先介绍怎么实现一棵异步树。
项目前准备:
1、首先你要搭建一个你熟悉的框架环境,然后再前台加入EasyUI的源码包,并在页面引入js和css等文件。本文的实例主要讲解怎么实现树,以SSH框架为例。如果还有不懂怎么搭建EasyUI框架的同学,可以在EasyUI的中文社区里找EasyUI的初级视频来看看,非常简单的。
2、建立数据库,比方说我们要通过树来展示你的菜单,那么就要先看一下EasyUI中tree的Data Format,也就是说我们要了解后台传给前台什么样式的Json格式。
从上面的文档截图可以看出,他的数据格式有以下属性:id,text,state,checked,attributes,children;
我们在设计数据库的时候,可以尽量的将节点id和节点名称分别设置成id和text,这样在前台解析Json的时候就能直接认出这些属性值,并显示出数据来。当然利用扩展的方式的话,你可以不必按照这些规范来,但是需要在tree控件里传入几个参数来传入属性值。
首先,建立一个t_menu表:(注释如图)
外键:
测试数据:
准备完以上的内容之后,我们开始做demo。
1、加入EasyUI的树控件:
<ul id="menuTree" class="easyui-tree" data-options="url:‘<%=basePath%>menuAction!getTreeNode.action‘,parentField:‘pid‘,lines:true,onLoadSuccess:function(node, data){$(this).tree(‘collapseAll‘)}"></ul>
解析:
data-options里的URL是Action的路径,p
arentField设置成我们model里的pid,
lines:true用来显示树节点前的加减号,
onLoadSuccess:function(node, data){$(this).tree(‘collapseAll‘)}用来设置关闭所有的树节点。
加入扩展js:
1 $.fn.tree.defaults.loadFilter = function (data, parent) { 2 var opt = $(this).data().tree.options; 3 var idFiled, 4 textFiled, 5 parentField; 6 if (opt.parentField) { 7 idFiled = opt.idFiled || ‘id‘; 8 textFiled = opt.textFiled || ‘text‘; 9 parentField = opt.parentField;10 11 var i,12 l,13 treeData =http://www.mamicode.com/ [],14 tmpMap = [];15 16 for (i = 0, l = data.length; i < l; i++) {17 tmpMap[data[i][idFiled]] = data[i];18 }19 20 for (i = 0, l = data.length; i < l; i++) {21 if (tmpMap[data[i][parentField]] && data[i][idFiled] != data[i][parentField]) {22 if (!tmpMap[data[i][parentField]][‘children‘])23 tmpMap[data[i][parentField]][‘children‘] = [];24 data[i][‘text‘] = data[i][textFiled];25 tmpMap[data[i][parentField]][‘children‘].push(data[i]);26 } else {27 data[i][‘text‘] = data[i][textFiled];28 treeData.push(data[i]);29 }30 }31 return treeData;32 }33 return data;34 };
2、Action类实现
首先是model类TMenu.java,映射数据库的类。
1 import java.util.HashSet; 2 import java.util.Set; 3 import javax.persistence.CascadeType; 4 import javax.persistence.Column; 5 import javax.persistence.Entity; 6 import javax.persistence.FetchType; 7 import javax.persistence.Id; 8 import javax.persistence.JoinColumn; 9 import javax.persistence.ManyToOne; 10 import javax.persistence.OneToMany; 11 import javax.persistence.Table; 12 13 /** 14 * TMenu entity. @author MyEclipse Persistence Tools 15 */ 16 @Entity 17 @Table(name = "t_menu", catalog = "easyui") 18 public class TMenu implements java.io.Serializable { 19 20 // Fields 21 22 private String id; 23 private TMenu TMenu; 24 private String text; 25 private String iconCls; 26 private String url; 27 private Set<TMenu> TMenus = new HashSet<TMenu>(0); 28 29 // Constructors 30 31 /** default constructor */ 32 public TMenu() { 33 } 34 35 /** minimal constructor */ 36 public TMenu(String id) { 37 this.id = id; 38 } 39 40 /** full constructor */ 41 public TMenu(String id, TMenu TMenu, String text, String iconCls, String url, Set<TMenu> TMenus) { 42 this.id = id; 43 this.TMenu = TMenu; 44 this.text = text; 45 this.iconCls = iconCls; 46 this.url = url; 47 this.TMenus = TMenus; 48 } 49 50 // Property accessors 51 @Id 52 @Column(name = "id", unique = true, nullable = false, length = 36) 53 public String getId() { 54 return this.id; 55 } 56 57 public void setId(String id) { 58 this.id = id; 59 } 60 61 @ManyToOne(fetch = FetchType.LAZY) 62 @JoinColumn(name = "pid") 63 public TMenu getTMenu() { 64 return this.TMenu; 65 } 66 67 public void setTMenu(TMenu TMenu) { 68 this.TMenu = TMenu; 69 } 70 71 @Column(name = "text", length = 100) 72 public String getText() { 73 return this.text; 74 } 75 76 public void setText(String text) { 77 this.text = text; 78 } 79 80 @Column(name = "iconCls", length = 50) 81 public String getIconCls() { 82 return this.iconCls; 83 } 84 85 public void setIconCls(String iconCls) { 86 this.iconCls = iconCls; 87 } 88 89 @Column(name = "url", length = 200) 90 public String getUrl() { 91 return this.url; 92 } 93 94 public void setUrl(String url) { 95 this.url = url; 96 } 97 98 @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "TMenu") 99 public Set<TMenu> getTMenus() {100 return this.TMenus;101 }102 103 public void setTMenus(Set<TMenu> TMenus) {104 this.TMenus = TMenus;105 }106 107 }
其次是model类Menu.java,此处的model是pageModel,是为了接应前台的name值的:
1 public class Menu { 2 3 private String pid;//父菜单ID 4 private String pText;//父菜单名称 5 private String id;//子菜单Id 6 private String text;//子菜单名称 7 private String iconCls;//子菜单图标 8 private String url;//子菜单路径 9 private String state;10 11 //---------------set/get--------------12 13 public String getPid() {14 return pid;15 }16 public void setPid(String pid) {17 this.pid = pid;18 }19 20 public String getpText() {21 return pText;22 }23 public void setpText(String pText) {24 this.pText = pText;25 }26 public String getId() {27 return id;28 }29 public void setId(String id) {30 this.id = id;31 }32 33 public String getText() {34 return text;35 }36 public void setText(String text) {37 this.text = text;38 }39 public String getIconCls() {40 return iconCls;41 }42 public void setIconCls(String iconCls) {43 this.iconCls = iconCls;44 }45 public String getUrl() {46 return url;47 }48 public void setUrl(String url) {49 this.url = url;50 }51 public String getState() {52 return state;53 }54 public void setState(String state) {55 this.state = state;56 }57 58 59 }
Action类:
1 package com.action; 2 3 4 import org.apache.struts2.convention.annotation.Action; 5 import org.apache.struts2.convention.annotation.Namespace; 6 import org.apache.struts2.convention.annotation.ParentPackage; 7 import org.springframework.beans.factory.annotation.Autowired; 8 9 import com.pageModel.Menu;10 import com.service.IMenuService;11 12 import com.opensymphony.xwork2.ModelDriven;13 14 @ParentPackage("basePackage")15 @Namespace("/")16 @Action(value="http://www.mamicode.com/menuAction")17 public class MenuAction extends BaseAction implements ModelDriven<Menu> {18 Menu menu=new Menu();19 @Override20 public Menu getModel() {21 // TODO Auto-generated method stub22 return menu;23 }24 private IMenuService menuService;25 26 public IMenuService getMenuService() {27 return menuService;28 }29 @Autowired30 public void setMenuService(IMenuService menuService) {31 this.menuService = menuService;32 }33 /**34 * 异步获得树节点35 */36 public void getTreeNode(){37 super.writeJson(menuService.getTreeNode(menu.getId()));38 }39 }
2、了解getTreeNode()方法的实现:
对应service的实现类:
1 package com.service.impl; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Map; 7 import java.util.Set; 8 9 import org.springframework.beans.BeanUtils;10 import org.springframework.beans.factory.annotation.Autowired;11 import org.springframework.stereotype.Service;12 13 import com.dao.IBaseDao;14 import com.model.TMenu;15 import com.pageModel.Menu;16 import com.service.IMenuService;17 18 @Service("menuService")19 public class MenuServiceImpl implements IMenuService {20 private IBaseDao<TMenu> menuDao;21 22 23 public IBaseDao<TMenu> getMenuDao() {24 return menuDao;25 }26 27 @Autowired28 public void setMenuDao(IBaseDao<TMenu> menuDao) {29 this.menuDao = menuDao;30 }31 32 33 @Override34 public List<Menu> getTreeNode(String id) {35 List<Menu> menus=new ArrayList<Menu>();36 StringBuffer hql=new StringBuffer();37 hql=hql.append("from TMenu t where ");38 Map<String, Object> map=new HashMap<String, Object>();39 if (id==null || "".equals(id)) {40 //返回总根节点41 hql=hql.append(" t.TMenu is null");42 43 } else {44 //异步加载当前id下的子节点45 hql=hql.append(" t.TMenu.id=:id");46 map.put("id", id);47 }48 List<TMenu> tMenus= menuDao.find(hql.toString(),map);49 for (TMenu tMenu : tMenus) {50 Menu menu=new Menu();51 BeanUtils.copyProperties(tMenu, menu);52 Set<TMenu> set=tMenu.getTMenus();53 if (set!=null && !set.isEmpty()) {54 menu.setState("closed"); //节点以根节点形式体现(文件夹)55 } else {56 menu.setState("open"); //节点 以叶子形式体现(文件)57 }58 menus.add(menu);59 }60 return menus;61 }62 63 }
最后展示实现效果:当单击加号的时候才会加载其子节点,异步实现了功能树。
下篇博客将介绍另一种加载树的方式,就是一次把所有的树节点都加载上来,显示扁平化数据。