在实际生产中树的构造是需要根据后台数据库中存放的内容动态加载的,例如一个系统中,不同的角色有不同的权限,他们所能进行的操作也是不同的,如果需要构造一个树形结构展现某个角色所能进行的操作,这就用到了树形结构。
ExtJs提供了动态加载树形结构的机制,这里就用到了TreeStore动态加载,常用的动态加载数据格式有JSON和XML。
这里我们看一下如何使用JSON格式数据动态加载属性结构。
首先看一下建立的TreeStore。
var tree_store = Ext.create('Ext.data.TreeStore', { id:'tree_store', proxy: { type: 'ajax', url: 'MyJsp.jsp', } });
这里我们通过ajax的方式向一个JSP请求数据。下面看TreePanel的定义。
var treePanel = Ext.create('Ext.tree.Panel', { id: 'tree_panel', title: '动态加载', region: 'west', width: 200, rootVisible: false, store: tree_store, listeners : { itemclick : tree_itemclick }, tools: [{ type: 'refresh', tooltip: '刷新', handler: function() {//Ext.data.Store load tree_store.load({ scope: this, callback: function(records, operation, success) { treePanel.getRootNode().eachChild(function(child) { child.expand(); }); } }); } } ], });
这里需要注意一点,这段代码是卸载onReady()函数中的,而且在加载treePanel之前调用tree_store的load方法。或者将tree_store写在treePanel里面,否则可能造成树形结构无法正常加载显示。
后台最主要的作用是将节点信息组成恰当的JSON字符串,如果需要加载的节点不多的话可以使用拼接字符串的方式,如果节点较多可以使用javaBean封装节点信息,然后通过循环的方式拼接。
下面我们先看一下节点类的定义。
public class Node { private String text;//节点显示字符串 private String id;//节点ID private boolean leaf;//是否是叶子节点 public String getText() { return text; } public void setText(String text) { this.text = text; } public String getId() { return id; } public void setId(String id) { this.id = id; } public boolean isLeaf() { return leaf; } public void setLeaf(boolean leaf) { this.leaf = leaf; } }
真实开发中可以从数据库中取出这些节点的一个集合信息,这里我们使用一个普通方法模拟一个节点信息的集合。
public ArrayList<Node> getRes(){ ArrayList<Node> result = new ArrayList<Node>(); Node node1 = new Node(); node1.setId("第一个节点的id"); node1.setLeaf(true); node1.setText("第一个节点"); Node node2 = new Node(); node2.setId("第二个节点的ID"); node2.setLeaf(true); node2.setText("第二个节点"); result.add(node1); result.add(node2); return result; }
下面我们看一下如何根据这个集合来拼接JSON字符
public String getJson(){ String result = "[{text:'1级文件夹',id:'host',children:["; ArrayList<Node> arrlist = getRes(); Iterator<Node> iterator = arrlist.iterator(); while(iterator.hasNext()){ Node node = iterator.next(); if(iterator.hasNext()) result +="{id:'"+node.getId()+"',text:'"+node.getText()+"',leaf:"+node.isLeaf()+"},"; else result +="{id:'"+node.getId()+"',text:'"+node.getText()+"',leaf:"+node.isLeaf()+"}"; } result+="]},{text:'2级文件夹',id:'operate',children:[{id:'addhost',text:'第三个节点',leaf:true}," + "{id:'addclient',text:'第四个节点',leaf:true}]}]"; return result; }
在result字符串定义和最后返回之前是使用最普通的字符串拼接的方法,这里一起进行测试。
然后我们看一下url中请求的JSP页面。
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <jsp:useBean id="service" class="service.Service"></jsp:useBean> <% request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); String json = service.getJson(); System.out.println(json); response.getWriter().write(json); %>
这样就可以在请求页面的过程中根据后台中的内容动态加载属性结构。
下面看一下效果图:
使用这种方式动态加载时将所有的几点信息一次全部加载,也就是当你点击展开一级文件夹或二级文件夹的时候他不会在想后台发送请求,这里通过firebug就能看出,如果树的层次比较深,在后台构造JSON字符串发送就会比较麻烦,这时可以使用异步加载,也就是当页面第一次加载的时候只会加载1级文件夹和2级文件夹,当点击展开1级文件夹或2级文件夹的时候这时会继续向后退发送请求,请求加载1级文件夹的子节点。关于异步加载将在下篇博客介绍。