在我以前写的一篇文章ExtJS4+Servlet/Struts2+JSON+accordion布局动态Ext.tree.Panel菜单,大家都对Ext.tree.Panel组件和Ext.tab.Panel组件相结合起来比较困惑。对于Ext.tree.Panel的异步加载也有问题。写这篇文章分享我对Ext开发的一些做法和认识。谈谈自己如何构建Ext应用框架的,下面让大家看看效果图:
Ext.Loader.setConfig({
enabled : true
});
Ext.Loader.setPath({
'Ext.ux' : 'ext4/ux',
'Ext.app' : 'ext4/app'
});
Ext.require(['Ext.app.Portlet', 'Ext.app.PortalColumn', 'Ext.app.PortalPanel',
'Ext.app.PortalDropZone', 'Ext.ux.TabReorderer',
'Ext.ux.TabCloseMenu']);
var title = Ext.create("Ext.panel.Panel", {
height : 80,
html : '业务基础平台',
region : 'north',
split : true,
bbar : [{
iconCls : 'icon-user',
text : '管理员'
},'-',{
text : Ext.Date.format(new Date(),'Y年m月d日')
},'->',{
text : '退出',
iconCls : 'icon-logout'
}],
bodyStyle : 'backgroud-color:#99bbe8;line-height : 50px;padding-left:20px;font-size:22px;color:#000000;font-family:黑体;font-weight:bolder;' +
'background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(153,187, 232, 0.4) ), color-stop(50%, rgba(153, 187, 232, 1) ),color-stop(0%, rgba(153, 187, 232, 0.4) ) )'
}); 这个是title,这个组件很简单,主要是显示了“业务基础平台”的系统名称,并配置了相关的样式。并定义了一个bbar,用于显示用户名,当前时间和退出按钮等信息。下面看tab:
var tab = Ext.create('Ext.tab.Panel', {
activeTab : 0,
enableTabScroll : true,
animScroll : true,
border : true,
autoScroll : true,
region : 'center',
split : true,
items : [{
iconCls : 'icon-activity',
title : '平台首页',
xtype:'portalpanel',
layout:'column',
items : [{
xtype : 'portalcolumn',
columnWidth : 0.7,
items:[{ title: '新闻动态',height : 150,iconCls : 'icon-news' },
{title: '最新通知',height : 150, iconCls : 'icon-notice' },
{title: '业绩报表',height : 150, iconCls : 'icon-chart'}]
},{
xtype : 'portalcolumn',
columnWidth : 0.3,
items:[{ title: '功能链接', height : 150, iconCls : 'icon-link'},
{title: '待办事项',height : 150,iconCls : 'icon-note' },
{title: '邮件列表', height : 150,iconCls : 'icon-email-list'}]
}]
}],
plugins: [Ext.create('Ext.ux.TabReorderer'),
Ext.create('Ext.ux.TabCloseMenu',{
closeTabText: '关闭面板',
closeOthersTabsText: '关闭其他',
closeAllTabsText: '关闭所有'
})]
});
var tree = Ext.create("Ext.panel.Panel", {
region : 'west',
title : "系统菜单",
width : 250,
iconCls : "icon-tree",
autoScroll : false,
layout : 'accordion',
collapsible : true,
layoutConfig : {
animate : true
},
split : true
}); 下面我们将这些组件放在viewport组件里面,展示出来:
Ext.create('Ext.container.Viewport',{
layout : 'border',
items : [title,tab,tree],
listeners : {
afterrender : function(){
Ext.getBody().mask('正在加载系统菜单....');
ajax({
url : "app",// 获取面板的地址
params : {
action : "list"
},
callback : addTree
});
}
}
});
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String action = request.getParameter("action");
initHeader(response);
if (action.equals("list")) {// 获取属面板列表
renderText(this.getTreePanelList(), response);
} else if (action.equals("node")) {
renderText(this.getTreeNodeList(request.getParameter("id")),
response);
}
}
public String getTreePanelList() {
String sql = "select t.id, t.text, t.component, "
+ " t.description, t.type, t.iconCls, t.sort "
+ " from resource t where t.parent_id is null";
return BaseDAO.findBySql(sql).toString();
}
public String getTreeNodeList(String id) {
String sql = "select t.id, t.text, t.component, "
+ " t.description, t.type, t.iconCls, t.sort,t.leaf "
+ " from resource t where t.parent_id = '" + id + "'";
return BaseDAO.findBySql(sql).toString();
}
这段代码的实现的是,通过参数判断是获取树面板还是树节点,BaseDAO.findBySql方法将返回的结果集转换成一个List<JSONObject>对象,获得数据后发送到页面,这里面有两个获得数据的方法:
function addTree(data) {
Ext.getBody().unmask();
for (var i = 0; i < data.length; i++) {
tree.add(Ext.create("Ext.tree.Panel", {
title : data[i].text,
iconCls : data[i].iconCls,
//useArrows: true,
autoScroll : true,
rootVisible : false,
viewConfig : {
loadingText : "正在加载..."
},
store : createStore(data[i].id),
listeners : {
afterlayout : function() {
if (this.getView().el) {
var el = this.getView().el;
var table = el
.down("table.x-grid-table");
if (table) {
table.setWidth(el.getWidth());
}
}
},
itemclick : function(view,node){
if (node.isLeaf()) {
if(node.data.type === 'URL'){
var panel = Ext.create('Ext.panel.Panel',{
title : node.data.text,
closable : true,
iconCls : 'icon-activity',
html : '<iframe width="100%" height="100%" frameborder="0" src="http://www.baidu.com"></iframe>'
});
tab.add(panel);
tab.setActiveTab(panel);
}else if(node.data.type === 'COMPONENT'){
var panel = Ext.create(node.data.component,{
title : node.data.text,
closable : true,
iconCls : 'icon-activity'
});
tab.add(panel);
tab.setActiveTab(panel);
}
}
}
}
}));
tree.doLayout();
}
}
var model = Ext.define("TreeModel", { // 定义树节点数据模型
extend : "Ext.data.Model",
fields : [{name : "id",type : "string"},
{name : "text",type : "string"},
{name : "iconCls",type : "string"},
{name : "leaf",type : "boolean"},
{name : 'type'},
{name : 'component'}]
});
var createStore = function(id) { // 创建树面板数据源
var me = this;
return Ext.create("Ext.data.TreeStore", {
defaultRootId : id, // 默认的根节点id
model : model,
proxy : {
type : "ajax", // 获取方式
url : "app?action=node" // 获取树节点的地址
},
clearOnLoad : true,
nodeParam : "id"// 设置传递给后台的参数名,值是树节点的id属性
});
}; 这段代码在我的那片文章中由说明,在这里就不再赘述,下面大家看看生成好的树面板的效果:
itemclick : function(view,node){
if (node.isLeaf()) { //判断是否是叶子节点
if(node.data.type === 'URL'){ //判断资源类型
var panel = Ext.create('Ext.panel.Panel',{
title : node.data.text,
closable : true,
iconCls : 'icon-activity',
html : '<iframe width="100%" height="100%" frameborder="0" src="http://www.baidu.com"></iframe>'
});
tab.add(panel);
tab.setActiveTab(panel);
}else if(node.data.type === 'COMPONENT'){
var panel = Ext.create(node.data.component,{
title : node.data.text,
closable : true,
iconCls : 'icon-activity'
});
tab.add(panel);
tab.setActiveTab(panel);
}
}
} 这里的业务逻辑是,判断点击的节点是否是叶子节点,如果在叶子节点的话再判断节点的类型,如果是URL,我这里做了简单的处理,嵌套百度到tab当中,如果是COMPONENT的话,创建对应组件,添加到tab组件当中。效果图: