ExtJS作为前端JS框架,在企业级系统建设方面占有相当大的地位。无论是在界面设计、页面缓存处理、跨浏览器、面向对象方面都非常优秀。而且还有一个非常优秀的文档。相信大部分人都是被其界面吸引,但是我们在透过界面看Ext的实现方式和思想真的是让人受益匪浅。也不废话了,Ext对于大家来说应该有所了解。
有很多人说:Ext难学、难用,找不到切入点。我个人感觉做Ext的东西,就是做数据。你要做什么东西首先得想明白的就是需要什么样的数据。当你明白了需要什么样的数据时,其他的配置性的东西只要去查查文档就可以了。实际引用中我们并不需要做很炫的效果,拘泥于细节,好多东西换个方式也能实现。抓住重点,有的放矢!
当我们对Ext的一个开发原则有了了解之后,我们就可以开始动手设计异步加载菜单了:
[ { "text":"通用代码", "iconCls":"", "leaf":true, "id":"CommonCodePanel" }, { "text":"系统资源", "iconCls":"", "leaf":true, "id":"ResourceListPanel" }, { "text":"系统角色", "iconCls":"", "leaf":true, "id":"RolePanel" } ]
这是一个Ext.tree.TreePanel需要的数据,数据是通过Ext.tree.TreeLoader对象加载的,具体怎么加载的我们不深究,我们只是准备好它需要的数据就可以了,
首先在Action里面从Service层获取定制的数据 @SuppressWarnings("unchecked") public String execute() { //树状菜单 if (user.getLayout().equals(CommonConstants.LAYOUT_EAST) | user.getLayout().equals(CommonConstants.LAYOUT_WEST)) { JSONArray array = this.systemService .getResourceTree("root",(List<Resource>) this.request.getSession().getAttribute (FrameworkConstants.SESSION_KEY_CURRENT_USER_COMPONENT));//系统缓存的角色和菜单对应关系 request.setAttribute("menuList", array); } else { //下拉按钮式菜单(稍候会讲) JSONArray array = this.systemService .getResourceMenu(null,(List<Resource>) this.request.getSession() .getAttribute(FrameworkConstants.SESSION_KEY_CURRENT_USER_COMPONENT)); request.setAttribute("menuList", array); } return dispatcher("/jsp/index.jsp"); }
在Service层中从数据库中获取数据,并组织成Ext.tree.TreePanel需要的数据:
public JSONArray getResourceTree(String id, List<Resource> all) { //id属性是方便异步加载,根据获取的ID,获取某个菜单的子菜单 JSONArray array = new JSONArray(); if (id == null || id.equals("root")) { //root为根节点的标志,这个可以任意取,约定好就行,在页面上要进行控制 for (Resource r : all) { if (r.getParent() == null) { JSONObject json = new JSONObject(); json.element("id", r.getId()); json.element("iconCls", r.getIcon()); json.element("text", r.getName()); array.add(json); } } } else { for (Resource r : all) { if (r.getParent() != null) { if (r.getParent().getId().toString().equals(id)) { JSONObject json = new JSONObject(); json.element("text", r.getName()); json.element("iconCls", r.getIcon()); if (r.getChildren() != null && r.getChildren().size() > 0) { json.element("leaf", false); json.element("id", r.getId()); } else { json.element("leaf", true); if (r.getComponent() != null) { json.element("id", r.getComponent()); } } array.add(json); } } } } return array; }
数据准备好了,剩下的就是在页面进行展示:
//层叠样式的菜单,当然后面就有树状样式的菜单了 var accordionPanel = new Ext.Panel({ title : '层叠菜单', iconCls : 'icon-accordion', autoScroll : false, layout : 'accordion', defaultType :'treepanel', activeItem : 0, layoutConfig : {animate : true} }); //导航面板 var navigationTab = new Ext.TabPanel({ activeTab : 0, enableTabScroll : true, animScroll : true, autoScroll : true, border : false, region : 'center', tabPosition: 'bottom', items : [accordionPanel] }); //将组织好的数据解析成JSON数据格式 var data = support.decodeJSON('${menuList}'); /***********************实现层叠样式菜单*************************/ //循环往层叠样式面板中插入面板 for ( var i = 0; i < data.length; i++) { accordionPanel.add({ title : data[i].text, iconCls : data[i].iconCls, autoScroll : true, rootVisible : false, //定义异步记载的根节点 root : new Ext.tree.AsyncTreeNode({id : data[i].id}), loader : new Ext.tree.TreeLoader({ dataUrl : ctx+'/system/index!get.do', requestMethod : 'post', clearOnLoad : true }), tools : [{ id : 'refresh', qtip : '刷新菜单', handler : function(a,b,panel){ panel.root.reload(); } }], listeners : {'click' : function(node){ support.addtab(node);//添加到主面板中 }, 'load' : function(node){ this.getLoader().baseParams = null;//加载完成后清除loader对象中的参数 }, 'beforeload' : function(node){ //这一步很关键,获取要节点的ID,取出子节点 this.getLoader().baseParams = {id : node.id}; } } }); } /************************实现树状样式菜单**************************/ var menuTree = new Ext.tree.TreePanel({ title : '树状菜单', iconCls : 'icon-tree', autoScroll : true, rootVisible : false, animCollapse : true, root : new Ext.tree.AsyncTreeNode({id : 'root'}), loader : new Ext.tree.TreeLoader({ dataUrl : ctx+'/system/index!get.do', requestMethod : 'post' }), tbar : [{ xtype : 'textfield', emptyText : '查找菜单....', width : 90, enableKeyEvents : true, listeners : { 'keyup' : function(){ filterTreeNode(this.getValue(),menuTree.root); } } }, '->', { iconCls : 'icon-collapse-all', //收缩按钮 tooltip:{text : '收缩全部'}, handler : function(){ menuTree.collapseAll() } },'-',{ iconCls : 'icon-expand-all',//展开按钮 tooltip:{text : '展开全部'}, handler : function(){ menuTree.expandAll(); } },'-',{ iconCls : 'icon-refresh', tooltip:{text : '刷新菜单'}, handler : function(){ menuTree.root.reload(); } }], listeners : {'click' : function(node){ support.addtab(node); }, 'load' : function(node){ this.getLoader().baseParams = null; }, 'beforeload' : function(node){ this.getLoader().baseParams = {id : node.id}; } } }); navigationTab.add(menuTree);
这个异步加载菜单就完成了,效果图:
层叠样式菜单:
树状样式菜单:
我的另外一篇文章,介绍的是几点的实例,有源码:http://blog.csdn.net/leecho571/article/details/7051825 ,QQ群:197331959