1. 程式人生 > >ext tree的非同步與同步載入

ext tree的非同步與同步載入

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");
     }

 });