ext tree的非同步與同步載入
阿新 • • 發佈:2018-12-30
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"); } });