ext中,对tree的展现方式有两种:一是每个node逐个加载,逐次查询数据库;一是一个tree一次加载完成,只查询一次数据库。此次查询数据库的方式也有两种,一种是普通的select查询方式:
select * from table
一种是采用数据库的树状查询方式:
select * from table start with org_id = 'xxx' connect by prior org_id = parent_id
当然这两种tree的加载方式不同,决定了相应的treeModel不同。treeModel的主要区别是后者比前者多了一个List<TreeGroupModel> children属性,即将孩子节点封装在了treeModel中。
一般习惯采用第一种的逐个加载节点的方式,这样做,对于事件的处理比较方便,比如更换图片,隐藏复选框等等,在loader时加一个listener事件即可,如:
loader.addListener("load",function(treeLoader,node) { node.eachChild(function(child) { var img = child.getUI().getIconEl(); if(child.attributes.group == false){ img.src = (child.attributes.groupLeader?"../desktop/icon/operator16x16.png":"../desktop/icon/onlineUser16x16.png"); } });
但是这种方式有一个大的弊端:如果要求,进入界面后,整个树形结构全部expand展现出来,那么就会出现展示慢的问题,如果整个树形结果比较庞大,那么所耗费的时间就不单单是2,3秒的问题了,比如有n个节点,那么就意味着前台要发送n次请求,而后台则要查询n此数据库,很是费时的。所以前者一般处理,开始只要求显示根节点,子节点的展示则要手动完成的情景,若要求进入界面就全部展示则建议采用第二种一次请求,一次查库的方式实现。
在采用第二种方式实现的时候,有两点要注意:一:后台递归调用算法的实现,二:前台js中事件的控制方式。
递归调用算法实现:
import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.commons.lang.builder.ToStringBuilder; import org.junit.Test; public class ListToTreeModelConverterTest { private List<GroupVO> buildMockListDatas() { List<GroupVO> mockDatas = new ArrayList<GroupVO>(); GroupVO root = new GroupVO(); root.setId(1l); root.setParentId(0l); GroupVO group1 = new GroupVO(); group1.setId(2l); group1.setParentId(1l); GroupVO group2 = new GroupVO(); group2.setId(3l); group2.setParentId(1l); GroupVO group11 = new GroupVO(); group11.setId(4l); group11.setParentId(2l); GroupVO group21 = new GroupVO(); group21.setId(5l); group21.setParentId(3l); mockDatas.add(root); mockDatas.add(group1); mockDatas.add(group2); mockDatas.add(group11); mockDatas.add(group21); return mockDatas; } private void iterateList(GroupTreeModel parentModel, List<GroupVO> mockDatas) { Long parentId = parentModel.getNodeId(); List<GroupTreeModel> childrenModel = null; Iterator<GroupVO> iterator = mockDatas.iterator(); while (iterator.hasNext()) { GroupVO group = iterator.next(); if (group.getParentId().equals(parentId)) { childrenModel = parentModel.getChildren(); if (childrenModel == null) { childrenModel = new ArrayList<GroupTreeModel>(); } GroupTreeModel childModel = new GroupTreeModel(); childModel.setNodeId(group.getId()); childModel.setParentNodeId(group.getParentId()); childrenModel.add(childModel); iterator.remove(); parentModel.setChildren(childrenModel); } } if (childrenModel != null && !childrenModel.isEmpty() && !mockDatas.isEmpty()) { for (GroupTreeModel model : childrenModel) { iterateList(model, mockDatas); } } } @Test public void convert() { List<GroupVO> mockDatas = buildMockListDatas(); GroupTreeModel rootModel = new GroupTreeModel(); if (mockDatas != null && !mockDatas.isEmpty()) { GroupVO rootGroup = mockDatas.get(0); rootModel.setNodeId(rootGroup.getId()); rootModel.setParentNodeId(rootGroup.getParentId()); mockDatas.remove(0); iterateList(rootModel, mockDatas); } System.out.println("\n\nthe model is:" + rootModel); } } class GroupVO { private Long id; private Long parentId; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Long getParentId() { return parentId; } public void setParentId(Long parentId) { this.parentId = parentId; } public String toString() { return ToStringBuilder.reflectionToString(this); } } class GroupTreeModel { private Long nodeId; private Long parentNodeId; private List<GroupTreeModel> children; public Long getNodeId() { return nodeId; } public void setNodeId(Long nodeId) { this.nodeId = nodeId; } public Long getParentNodeId() { return parentNodeId; } public void setParentNodeId(Long parentNodeId) { this.parentNodeId = parentNodeId; } public List<GroupTreeModel> getChildren() { return children; } public void setChildren(List<GroupTreeModel> children) { this.children = children; } public String toString() { return ToStringBuilder.reflectionToString(this); } }
js文件中事物控制:
注意此时由于是一次加载完成的,所以在loader.addListener中只能捕捉到一个节点,即根节点,而其他节点则是无法触发的,所以建议使用extAPI中提供的其他事件处理,如对于节点图片的转化则邮以前的loader中变为了现在的beforechildrenrendered事件中:
tree.addListener("beforechildrenrendered",function(node) { var img = node.getUI().getIconEl(); if(node.attributes.group == false){ img.src =(node.attributes.groupLeader?"../desktop/icon/operator16x16.png":"../desktop/icon/onlineUser16x16.png"); } });