最近在开发一套物流管理系统的前端界面,技术选型要求必须基于 ExtJS 4.1。说实话,这个版本虽然成熟稳定,但网上能找到的实战教程相对较少,尤其是一些界面联动的细节,往往需要反复查阅 API 并不断试错才能跑通。下面就把左侧功能树与右侧 TabPanel 联动的完整思路和核心代码拆解出来,希望能对遇到类似需求的朋友有所帮助。
1. 左侧的功能树
首先定义一个树形结构,作为左侧导航菜单。这里采用 Ext.tree.Panel,关键配置如下:
Ext.define("AM.view.SystemTree", {
extend : 'Ext.tree.Panel',
alias : 'widget.systemTree',
rootVisible : false, // 不展示 ROOT
displayField : 'text',
// title:'物流运输系统',
viewConfig : {
plugins : {
ptype : 'treeviewdragdrop'
},
listeners : {
drop : function(node, data, overModel, dropPosition, options) {
alert("把: " + data.records[0].get('text') + " 移动到: "
+ overModel.get('text'));
}
}
},
dockedItems : [ {
xtype : 'toolbar',
items : [ {
xtype : 'button',
id : 'allopen',
icon : 'resources/img/lock_open.png',
text : '展开全部'
}, {
xtype : 'button',
id : 'allclose',
icon : 'resources/img/lock.png',
text : '收起全部'
} ]
} ],
root : {
text : 'root',
leaf : false,
id : '0',
children : [ {
text : '运输管理',
checked : false,
leaf : false,
icon : 'resources/img/folder_user.png',
id : '01',
children : [ {
text : '车辆信息管理',
checked : false,
icon : 'resources/img/report_edit.png',
leaf : true,
id : 'vehiclelist' // 关键:这里的 id 必须指定为待打开视图的别名
}]
}]
}
});
要点:
- 树组件一定要设置
alias,便于后续引用。 - 子节点的
id必须等于右侧对应视图的alias值——这是联动机制的核心。后面会看到,点击树节点时正是通过这个 id 来精准定位具体视图。
2. 需要打开的对应视图
以“车辆信息管理”为例,定义一个 GridPanel,注意别名和 id 必须保持一致:
Ext.define("AM.view.transportation.VehicleList",{
extend:'Ext.grid.Panel',
alias:'widget.vehiclelist', // 别名必须与树节点 id 一致
id:'vehiclelist',
store:'VehicleStore',
// ......中间代码省略
columns : [
{text:'车辆编号',dataIndex:'vehicleNo',
field:{
xtype:'textfield',
allowBlank:false
}
},
{text:'车辆描述',xtype:'templatecolumn',
tpl:'车辆的编号为{vehicleNo} 所在地区为{vehicleArea}'
}
],
initComponent:function(){
this.callParent(arguments);
}
});
3. 建立右侧的 TabPanel
主界面右侧放置一个 TabPanel,用于承载各个功能页面。初始化时先放一个默认的首页:
Ext.define('AM.view.TabPanel',{
extend: 'Ext.tab.Panel',
alias:'widget.tabpanel',
closeAction: 'destroy',
defaults :{
bodyPadding: 10
},
items: [{
title: '主页',
autoLoad:'content.jsp' // 简单的 panel 加载页面
}]
});
4. 设置点击 tree 的触发事件
最后是关键一步:监听树节点的点击事件,根据节点 id 在 TabPanel 中动态添加或激活对应的视图。注意通过层层定位找到右侧的 tabpanel 组件:
'systemTree':{
itemclick:function(tree,record,item,index,e,options){
var tabs = tree.ownerCt.ownerCt.ownerCt
.child('#center-grid').child("#tabpanel");
// 获取当前点击的节点
var treeNode=record.raw;
var id = treeNode.id;
var text=treeNode.text;
// 获取与树节点 id 相同的 tab 标签
var tab = tabs.getComponent(id);
if(!tab){ // 如果不存在则新建
tabs.add({
id:id,
closable: true,
title:text,
iconCls:id,
xtype:id // 将 id 作为 xtype,渲染对应的视图
}).show();
}else{ // 如果已存在则激活
tabs.setActiveTab(tab);
}
}
},
效果图如下(来自实际项目截图):

总结
ExtJS 构建的界面视觉效果非常出色,但新版本的学习曲线相对陡峭,尤其网上能找到的完整实战案例不多。遇到问题时最有效的方法还是仔细阅读 API 文档,并对照官方示例逐步调试。上面这套左侧树 + 右侧 TabPanel 联动的设计模式,在后台管理系统中极为常用,代码量不大,只要把 id 和 alias 的映射关系理清楚,基本就能顺利实现。刚接触 ExtJS 不久,如有不当之处欢迎指正交流。
