使
用JS生成树形结构的菜单是基于J2EE的B/S系统常用的UI方式。但长期以来的问题是同步(即一次加载整棵树)加载一棵完整的树给前台及后台同时带来
压力,由于加载数据及渲染时间过长使用户体验度很低。Ajax的异步数据传输方式是解决此问题的较好方式,即每次只加载一层节点,当需要时才加载下级节
点,这样页面无需一次加载解决了此问题。
Ext的TreePanel组件提供了此功能即异步树(asynchronism tree),使用其实现需以下两步:
后台数据加载的实现,并以JSON形式提供给前台。
前台Ext的Tree组件实现。
实现预览:
1. 首先是JavaBean的节点模型(Tree Node Model):
Java代码
/**
* Method: 异步加载树型结点
* Origin Time: 2008-8-15 下午03:56:28
*
* @author Seraph
* @email: seraph115@gmail.com
*/
publicclassAsyncTreeNode {
privateString id;
privateString text;// 结点显示名称
privatebooleanleaf;// 是否为叶子结点
privatebooleandisabled;// 是否可用
privateString cls;// 显示的样式,file、folder
privateString iconCls;// 结点图标样式
privateString href;// 点击后时的链接
privateString hrefTarget;// 在何frame中显示
privatebooleandraggable;// 是否可拖拽
// Omit the get and set method
... ...
}
/**
* Method: 异步加载树型结点
* Origin Time: 2008-8-15 下午03:56:28
*
* @author Seraph
* @email: seraph115@gmail.com
*/
public class AsyncTreeNode {
private String id;
private String text; // 结点显示名称
private boolean leaf; // 是否为叶子结点
private boolean disabled; // 是否可用
private String cls; // 显示的样式,file、folder
private String iconCls; // 结点图标样式
private String href; // 点击后时的链接
private String hrefTarget; // 在何frame中显示
private boolean draggable; // 是否可拖拽
// Omit the get and set method
... ...
}
数据库中的表结构:
COLUMN_NAME
DATA_TYPE
ID
NUMBER
PARENT
NUMBER
TEXT
VARCHAR2
LEAF
VARCHAR2
DISABLED
VARCHAR2
CLS
VARCHAR2
ICON_CLS
VARCHAR2
HREF
VARCHAR2
HREF_TARGET
VARCHAR2
取下级节点的接口定义:
Java代码
/**
* Method: 获取异步加载树型子结点
* Author: Seraph
* Origin Time: 2008-9-9 下午05:46:02
*
* @param menuId 当前结点的id
* @return 下级节点组成的List
*/
publicList getLowerTreeNodes(String menuId);
/**
* Method: 获取异步加载树型子结点
* Author: Seraph
* Origin Time: 2008-9-9 下午05:46:02
*
* @param menuId 当前结点的id
* @return 下级节点组成的List
*/
public List getLowerTreeNodes(String menuId);
数据提供的Spring的Controller:
Java代码
/**
* Method:
* Origin Time: 2008-8-15 上午11:07:55
* @author Seraph
* @email: seraph115@gmail.com
*/
publicclassAsyncTreeProviderControllerextendsJsonProviderController {
privateTreeManager treeManager;
publicvoidsetTreeManager(TreeManager treeManager) {
this.treeManager = treeManager;
}
protectedModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throwsException {
String rootId = request.getParameter("id");
List list = treeManager.getLowerTreeNodes(rootId);
super.pushJsonResponse(response, list);
returnnull;
}
}
/**
* Method:
* Origin Time: 2008-8-15 上午11:07:55
* @author Seraph
* @email: seraph115@gmail.com
*/
public class AsyncTreeProviderController extends JsonProviderController {
private TreeManager treeManager;
public void setTreeManager(TreeManager treeManager) {
this.treeManager = treeManager;
}
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String rootId = request.getParameter("id");
List list = treeManager.getLowerTreeNodes(rootId);
super.pushJsonResponse(response, list);
return null;
}
}
此步将查询到的下级结点的List转换为JSON数据通过Ajax方式返回给Ext的TreePanel组件用以渲染下级结点。
PS: 推荐使用json-lib来转换javabean为json数据。下面是json-lib的maven的dependency。
Xml代码
net.sf.json-lib
json-lib
2.2.2
net.sf.json-lib
json-lib
2.2.2
2. JavaScript的Ext TreePanel组件实现:
Js代码
/**
* async-tree.js Power by YUI-EXT and JSON.
*
* @author Seraph
* @email seraph115@gmail.com
*/
varAsyncTree = {
author: "Seraph",
version: "0.1.0"
};
// -> Configuration of tree. e.g: CG[1]
varCG = {
1: "asyncTreeProvider.do",
2: "async"
};
// -> Root-node name in Chinese. e.g: CN[1]
varCN = {
1: "菜单",
2: "配置"
};
// -> Root-node ID of tree. e.g: ID[1]
varID = {
1: "-1",
2: "-2"
};
Ext.onReady(function(){
varTree = Ext.tree;
varmyTreeLoader =newExt.tree.TreeLoader({
url: CG[1]
});
myTreeLoader.on("beforeload",function(treeLoader, node) {
myTreeLoader.baseParams.id = node.attributes.id;
}, myTreeLoader);
vartree =newTree.TreePanel({
el:'tree1',
autoScroll:true,
autoHeight: true,
border: false,
animate:true,
enableDD:true,
rootVisible:false,
containerScroll: true,
loader: myTreeLoader,
root: {
nodeType: CG[2],
text: CN[1],
id: ID[1]
}
});
tree.render();
tree.getRootNode().expand();
});
/**
* async-tree.js Power by YUI-EXT and JSON.
*
* @author Seraph
* @email seraph115@gmail.com
*/
var AsyncTree = {
author: "Seraph",
version: "0.1.0"
};
// -> Configuration of tree. e.g: CG[1]
var CG = {
1: "asyncTreeProvider.do",
2: "async"
};
// -> Root-node name in Chinese. e.g: CN[1]
var CN = {
1: "菜单",
2: "配置"
};
// -> Root-node ID of tree. e.g: ID[1]
var ID = {
1: "-1",
2: "-2"
};
Ext.onReady(function(){
var Tree = Ext.tree;
var myTreeLoader = new Ext.tree.TreeLoader({
url: CG[1]
});
myTreeLoader.on("beforeload", function(treeLoader, node) {
myTreeLoader.baseParams.id = node.attributes.id;
}, myTreeLoader);
var tree = new Tree.TreePanel({
el:'tree1',
autoScroll:true,
autoHeight: true,
border: false,
animate:true,
enableDD:true,
rootVisible:false,
containerScroll: true,
loader: myTreeLoader,
root: {
nodeType: CG[2],
text: CN[1],
id: ID[1]
}
});
tree.render();
tree.getRootNode().expand();
});