一、创建树
Extjs4 中tree组件功能强大,是extjs学习过程中的重要一环。tree组件作为extjs4中的重要组件之一,在几乎所有的extjs系统中都有使用,本人在实际使用过程中也曾遇到过很多困扰,但最终还是通过各种方式加以解决了,下面与大家分享一下个人心得,希望能给大家带来点帮助。
通过Sencha Arthitect2 可以用所见即所得的方式生成任何你所想要的Extjs界面元素,而无需花太多时间去编写代码, 大大提高了编程效率。
在toolbox里选择Trees标签,拖动tree panel 至已经布局好的界面布局内,如BORDER布局的WEST,默认情况下,treepanel 里只有一列(tree column)。此时treepanel里没有节点,如若你要建立的是静态树,那么你只需要通过属性编辑器编辑treepanel 的root属性为treepanel添加默认的根节点,此属性为object类型,可接受json类型对象如下,此时创建的树为同步树,不需要与服务器交互获取节点数据。
root: {text: 'root',leaf: false,childern:[{text:'child1',leaf:true}]}
Sencha Arthitect2 中treepanel组件
配置treepanel的root属性:
二、异步树
1、Model、Proxy、Store
要建立异步树,就必须建立与服务器端进行数据对接的Extjs 模型(model),用于接收规定类型的数据。Proxy用于指定该Model或Store通过何种渠道与服务器通信,Proxy用于配置通信方式(ajax、localstorage、memory、rest)、通信地址以及数据读取器reader(json、array、xml)。而store则是负责管理多个Model实例的集合,即数据的实际存储空间。通常情况下,treepanel配置store属性,store中配置Model与Proxy,但根据实际需要,也可将Proxy直接配置在Model中,以实现多个组件公用同一个Model,而无需设置store。总之Extjs4的数据管理结构灵活,多多实践才能完全掌握。
Ext.define('MyApp.store.MyJsonTreeStore', {
extend: 'Ext.data.TreeStore',
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
storeId: 'MyJsonTreeStore',
defaultRootId: 1,
root: {
text: '工程编号',
leaf: false
},
proxy: {
type: 'ajax',
url:'test.action',
extraParams: {
en: 'default'
},
reader: {
type: 'json'
}
},
fields: [
{
name: 'text',
type: 'string'
},
{
name: 'desc',
type: 'string'
},
{
name: 'en',
type: 'string'
},
{
name: 'wm',
type: 'string'
}
]
}, cfg)]);
}
});
上述代码定义了一个treestore,并配置了proxy与fields选项,fields在这里即Model也可将其单独配置在Model中,然后在此处指定model选项。
2、动态加载
如果树节点数目过多,一次性加载会出现加载速度慢的问题,这时最好使用Extjs4的动态加载技术,可以按实际需要及时从服务器获取指定的节点数据。而我们所要做的主要就是设置treeepanel的根节点、动态加载事件监听、后台服务器程序代码三块,其余事项皆由EXTJS自动完成。
1、根节点:当给treepanel配置store后,store中的root属性将会覆盖treepanel中的root属性,这里特别注意,Extjs4默认的根节点id为‘root',可以设置成自己定义的值,如1:defaultRootId:1。默认情况下,节点id值用node属性传递至服务器,如果需更多参数,可以在store属性extraParams里设置。如上述代码中的en参数设置。
2、事件监听:当双击树节点的时候,系统自动设置node参数及extraParams中的参数并通过GET的方式向服务器发送请求,但是此时extraParams中的参数是固定的,即每次传递的都是一样,即上述配置的’default‘。所以需要在treepanel load之前将extraParams里的参数重新赋值,这里我们通过beforeload事件来设置我们的参数,代码如下:
onTreepanelBeforeLoad: function(store, operation, options) {
operation.params.en=operation.node.data.en;
}
这样每次点击树节点前边的加号或双击节点后,系统都会将en参数设置成节点的en属性值并发送至服务器实现动态加载,而服务器处理代码可依据传递的参数返回不同的节点的数据。
3、后台代码:
JSONArray json = new JSONArray();//初始化JSON数组对象
if (node.equals("1")) { //根据不同节点ID返回不同的JSON节点数据
List<EngineNumber> ens = DBManager.getAllEngines();
for (int i = 0; i < ens.size(); i++) {
JSONObject object = new JSONObject();//json对象
object.put("id", "E" + String.format("%04d", i) );//后台返回的树节点id值
object.put("text", ens.get(i).getFullname()); //树节点显示内容
object.put("desc", "【" + ens.get(i).getEtype() + " | " + ens.get(i).getTaifeng() + "】"); //描述列显示的值
object.put("en", ens.get(i).getEnumber()); //用于获取子节点的参数值
object.put("wm", ens.get(i).getW_m());
//以下为非数据属性
object.put("leaf", false); //是否为叶子节点
object.put("iconCls", "enginenumber");//图标样式
json.put(object);
}
} else if (node.startsWith("E") ) { //根据不同节点ID返回不同的JSON节点数据
List<GroupTreeNode> groups = DBManager.getGroupsOfEnginenumber(this.en);
for (int i = 0; i < groups.size(); i++) {
JSONObject obj1 = new JSONObject();
obj1.put("id", "G"+node + String.format("%04d", i));
obj1.put("text", groups.get(i).getGroupname());
obj1.put("desc", groups.get(i).getName());
obj1.put("en", this.en);
//obj1.put("wm", this.wm);
obj1.put("leaf", true);
obj1.put("iconCls", "file");
json.put(obj1);
}
}
ActionContext ctx = ActionContext.getContext();
HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print(json.toString());//将json对象输出到前台
return null;
3、自动加载
有些系统需要具备用户操作状态记忆功能,对于树而言就是要在每次打开系统时自动展开节点至上次退出时的状态。这就涉及到EXTJS4的自动加载与节点持久化技术了。用户节点展开状态要持久化,并在打开系统时自动展开,即可实现状态恢复。对于EXTJS4而言,其实是非常容易实现的。下面就具体介绍一下本人的实践。
1、设置自动加载
EXTJS4的自动加载就是指设置树的根节点自动加载,当设置根节点自动加载后,系统初始化时会首先自动加载根节点的子节点,再依据子节点属性expanded值来决定是否继续加载子节点,以此类推,遍历整棵树的节点状态。设置自动加载就是设置treestore的autoLoad: true。
2、设置持久化字段
当然获得了EXTJS系统的自动加载支持后,如何实现树节点状态的保存是自动加载的关键。上述代码中我们定义了树节点的4个属性,这些属性是用户自定义的,非EXTJS的内置属性。EXTJS4中NodeInterface中有20几个内置属性,这其中涉及到自动加载的是expanded属性,通过覆盖该属性定义就能够实现树状态的持久化。在treestore的fields中添加{name:'expanded',type:'boolean',persist:true},确保当调用store.sync()方法时,系统会将节点状态有所变化的节点数据通过Post的方式发送到服务器实现持久化。下图是树状态变化后,调用同步方法时的服务器请求。
系统将id为1的根节点状态通过expanded属性告知服务器。当然前提是需要配置treestore的api:update:'update.action'。
3、设计后台持久化代码
设计update业务代码,并辅以精良的数据库设计,完成最终的持久化。当系统下次登录时,将其通过子节点属性的方式返回。jsonobject.put("expanded",true);