在我以前写的一篇文章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组件当中。效果图: