ExtJS5学习之MVC

     写完第一篇Hello World之后,我就一直在准备着弄弄MVC,整了2天终于弄好了,遇到问题,也只能靠自己.
其实就是用ExtJS5 搭个后台界面:

ExtJS5学习之MVC_第1张图片
 啥都不说了,上代码。
首先需要一个app.js来定义一个ExtJS的Application,Application里去启动运行ExtJS的程序

App.js

Ext.QuickTips.init();
Ext.Loader.setConfig({
	enabled : true
});

Ext.Loader.setPath({
	'Ext.ux' : 'extjs/ux',
	//'Ext.app' : 'extjs/app',
	'Portal.view' : 'extjs/app',
	'OA.util' : 'app/util'
});

/**
 * 加载ExtJS插件文件
 */
Ext.require(
	[
		'Portal.view.Portlet',
		'Portal.view.PortalColumn',
		'Portal.view.PortalPanel',
		'Portal.view.PortalDropZone',
		
		'Ext.ux.TabReorderer',
		'Ext.ux.BoxReorderer',
		'Ext.ux.TabCloseMenu',
		'Ext.ux.PageSizePaging',
		'OA.util.AppUtil'
	]
);
Ext.application({
    requires: ['Ext.container.Viewport','OA.view.Viewport'],
    //项目名称简称
    name: 'OA',
    appFolder: 'app',
    autoCreateViewport: true,
    //控制器注册
    controllers:[
        'AppController',
        'user.UserController'
    ],
    
    launch: function () {
    	//Ext.create('OA.view.Viewport');
    }
});

 app.js里有个autoCreateViewport属性,即自动创建Viewport容器,我们知道ExtJS的所有组件都是需要放进这个总容器里的,当然viewport不是必须的哈。在ExtJS4.x的时候,是需要显示的在launch里去create我们的viewport容器,autoCreateViewport可以接收true/false,true的话就会自动到app/view下查找Viewport.js文件,自动帮我们加载并帮我们创建viewport容器,这是5.x后的新特性。当然你手动create还是可行的。此外,autoCreateViewport也可以接收一个Viewport类的全路径,即指定自动加载哪个viewport.举个例子:autoCreateViewport: "OA.view,Viewport",这样,如果你的viewport不在默认app/view路径下时,就可以手动指定要加载的viewport的路径。

 

Viewport.js

/*********************全局视图容器类************************/
Ext.define("OA.view.Viewport",{
    extend:'Ext.container.Viewport',
    requires:['Ext.container.Viewport','OA.view.MainPanel'],
    alias : 'widget.baseviewport',
    alternateClassName: ["OA.Viewport"],
    layout: 'fit',
    loadMask:{msg : '正在加载,请稍候...'},
    items: [
    	{
    		xtype: 'mainpanel'
    	}
    ]
});

 Viewport里就放了一个mainpanel子组件,采用fit布局是为了让他能充满整个屏幕。

 

MainPanel.js

 

Ext.define("OA.view.MainPanel",{
    extend:'Ext.panel.Panel',
    alias : 'widget.mainpanel',
    alternateClassName: ["OA.MainPanel"],
    requires: ['OA.view.TopPanel','OA.view.BottomPanel','OA.view.LeftPanel','OA.view.CenterPanel'],
    layout: 'border',
    border: 0,
    initComponent: function () {
        var me = this;
        me.items = [
            {
                xtype: 'toppanel'
            },
            {
                xtype: 'bottompanel'
            },
            {
                xtype: 'leftpanel'
            },
            {
                xtype: 'centerpanel'
            }
        ];
        me.callParent(arguments);
    }
});

 MainPanel里采用border布局,分别放了4个panel,上下左右,ExtJS的经典布局,你懂的。

 

上下左右4个panel的代码我直接贴了,代码太多就不一一解释了。

TopPanel.js

 

/**********************顶部Panel***********************/
Ext.define("OA.view.TopPanel",{
    extend:'Ext.panel.Panel',
    requires:["OA.view.ThemeMenu"],
    alias : 'widget.toppanel',
    alternateClassName: ["OA.TopPanel"],
    height: 50,
    split: false,
    border: 0,
    collapsible: false,
    titleCollapse: false,
    region: 'north',
    initComponent : function() {
        var me = this;
        me.items = [
		    {
		    	title: 'OA管理系统',   
		        xtype: 'panel',
		        margins:'0 0 5 0',
		        tbar:[
		            '->',
		            '益达,欢迎您!',
		            new Date().format("yyyy年MM月dd日    hh:mm:ss  w"),
		            {
		                text:'修改密码'            
		            },
		            {
		                text:'退出'            
		            },
		            {
		                text: '换肤',
	            		//iconCls: 'theme',
	            		menu: {xtype: 'thememenu'}
		            }
		       ]
		    }
    	];
    	me.callParent(arguments);
    }
});

 BottomPanel.js

 

 

/**********************底部Panel***********************/
Ext.define("OA.view.BottomPanel",{
    extend:'Ext.panel.Panel',
    alias : 'widget.bottompanel',
    alternateClassName: ["OA.BottomPanel"],
    height: 20,
    border: 0,
    split: false,
    collapsible: false,
    titleCollapse: false,
    draggable: false,
    region: 'south',
    initComponent: function () {
    	var me = this;
    	Ext.apply(me, {
            tbar: ['->','OA by yida']
        });
    	me.callParent(arguments);
    }
});

 LeftPanel.js

 

 

/*********************左侧Panel************************/
Ext.define("OA.view.LeftPanel",{
    extend:'Ext.panel.Panel',
    requires:["OA.view.LeftTreePanel"],
    alias : 'widget.leftpanel',
    alternateClassName: ["OA.LeftPanel"],
    
    initComponent : function(){
    	Ext.apply(this,{
    		id : "leftPanel",
		    title: '导航菜单',
		    width: 200,
		    height: "100%",
		    border: true,
		    collapsed: false,
		    collapsible: true,
		    animCollapse: true,
		    collapseMode: 'mini',
		    autoScroll: false,
		    containerScroll: true,
		    split: true,
		    resizable: false,
		    region: 'west',
		    layout: 'accordion',
		    layoutConfig : { 
		    	titleCollapse: false,   
                animate : true, //动态切换树空间 
                activeOnTop: true,
                multi:false
            }  
    	});
        this.callParent(arguments);
    }
});

 CenterPanel.js

 

 

/*******************中间Panel**************************/
Ext.define("OA.view.CenterPanel",{
    extend:'Ext.tab.Panel',
    requires:['Ext.tab.Panel'],
    alias : 'widget.centerpanel',
    alternateClassName: ["OA.CenterPanel"],
    id : "centerPanel",
    width: '100%',
    border: 0,
    enableTabScroll: true,
    autoScroll: true,
    activeItem: 0,
    region: 'center',
    layout: 'fit',
    initComponent : function() {
        var me = this;
        me.callParent(arguments);
    },
    items: [
        {  
            //iconCls : 'icon-activity',  
            title : '平台首页',  
            xtype:'portalpanel',  
            layout:'hbox',  
            items : [
            	{  
                    xtype : 'portalcolumn',  
                    columnWidth : 0.7,  
                    items:[
                    	{title: '新闻动态',height : 180},  
                        {title: '最新通知',height : 180},  
                        {title: '业绩报表',height : 180}
                    ]  
                },
                {  
                    xtype : 'portalcolumn',  
                    columnWidth : 0.3,
                    items:[
                    	{title: '常用功能', height : 180},  
                        {title: '待办事项',height : 180},  
                        {title: '邮件列表', height : 180}
                    ]  
                }
            ]  
        }
    ],
    listeners: {
    	resize :function(p, width, height,oldWidth,oldHeight, eOpts) {
    		p.updateLayout();
    	}
    }
});

 

 

最后贴一下AppUtil.js工具类

/**
 * JavaScript-Date日期类型格式化<br/>
 * 使用示例:
 * var date = new Date();
 * alert(date.format("yyyy-MM-dd hh:mm:ss"));
 * @param {} format
 * @return {}
 */
Date.prototype.format = function(format){
 var _week = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六']; 
 var o = {
  "M+" :  this.getMonth()+1,  //month 月
  "d+" :  this.getDate(),     //day 日
  "h+" :  this.getHours(),    //hour 时
  "m+" :  this.getMinutes(),  //minute 分
  "s+" :  this.getSeconds(), //second 秒
  "q+" :  Math.floor((this.getMonth()+3)/3),  //quarter季度
  "S"  :  this.getMilliseconds(), //millisecond毫秒
  "w"  :  _week[this.getDay()+""]   //星期几
  }
  
   if(/(y+)/.test(format)) {
    format = format.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));
   }
 
   for(var k in o) {
    if(new RegExp("("+ k +")").test(format)) {
      format = format.replace(RegExp.$1, RegExp.$1.length==1 ? o[k] : ("00"+ o[k]).substr((""+ o[k]).length));
    }
   }
 return format;
}

/**
 * 在原日期基础上添加或减去指定天(年,月,日,小时,分钟,秒)数<br/>
 * interval参数:
 * y       年 
 * q       季度 
 * m       月 
 * d       日 
 * w       周 
 * h       小时 
 * n       分钟 
 * s       秒 
 * ms      毫秒 
 * 
 * number参数:时间间隔,必须为数字,为正数表示获取指定间隔的未来的日期,为负数表示过去的日期
 * @param {} interval
 * @param {} number
 * @return {}
 */
Date.prototype.dateAdd = function(interval,number) 
{ 
    var d = this; 
    var k={'y':'FullYear', 'q':'Month', 'm':'Month', 'w':'Date', 'd':'Date', 'h':'Hours', 'n':'Minutes', 's':'Seconds', 'ms':'MilliSeconds'}; 
    var n={'q':3, 'w':7}; 
    eval('d.set'+k[interval]+'(d.get'+k[interval]+'()+'+((n[interval]||1)*number)+')'); 
    return d; 
} 

/**
 * 用于计算两个日期之间的时间间隔<br/>
 * 使用此方法还能比较两个日期的大小,如果返回值大于0,表示objDate2比较大,
 * 如果小于0,表示objDate2比较小
 * @param {} interval
 * @param {} objDate2
 * @return 返回相差的毫秒数
 */
Date.prototype.dateDiff = function(interval,objDate2) 
{ 
    var d=this, i={}, t=d.getTime(), t2=objDate2.getTime(); 
    i['y']=objDate2.getFullYear()-d.getFullYear(); 
    i['q']=i['y']*4+Math.floor(objDate2.getMonth()/4)-Math.floor(d.getMonth()/4); 
    i['m']=i['y']*12+objDate2.getMonth()-d.getMonth(); 
    i['ms']=objDate2.getTime()-d.getTime(); 
    i['w']=Math.floor((t2+345600000)/(604800000))-Math.floor((t+345600000)/(604800000)); 
    i['d']=Math.floor(t2/86400000)-Math.floor(t/86400000); 
    i['h']=Math.floor(t2/3600000)-Math.floor(t/3600000); 
    i['n']=Math.floor(t2/60000)-Math.floor(t/60000); 
    i['s']=Math.floor(t2/1000)-Math.floor(t/1000); 
    return i[interval]; 
}

/**
 * 获取数组中某元素的索引【索引从零开始计算】
 * @param {} o
 * @return {}
 */
Array.prototype.indexOf = function(o){
    for(var i = 0,len=this.length; i<len;i++){
		if(this[i]  == o){
   			return i;
		}
    }
    return -1;
}

/**
 * 删除数组中某元素
 * @param {} o
 * @return {}
 */
Array.prototype.remove = function(o){
    var index = this.indexOf(o);
    if(index != -1){
        this.splice(index,1);
    }
    return this;
}

/**
 * 去除数组中重复数据
 * @param {} o
 * @return {}
 */
function removeDuplicateArray(o){
    var obj={},ret=[],i=0;
    for(var a in o){
        obj[o[a]]=o[a];
    }
    for(ret[i++] in obj);
    return ret;
}

/**
 * 去除字符串中重复字符
 * @param {} str
 * @return {}
 */
function removeDuplicateString(str){
    var obj={},ret="";
    for(var i=0;i<str.length;i++){
    	var s=str.slice(i,i+1);
    	obj[s]=s;
    }
    for(s in obj){
    	ret += obj[s];
    };
    return ret;
}

/**
 * 去除数组或字符串中的重复字符
 * @param {} o
 * @return {}
 */
function removeDuplicate(o){
    return typeof(o)=="object"?removeDuplicateArray(o):removeDuplicateString(o);
}

/**
 * 删除字符串中重复字符
 * @param {} o
 * @return {}
 */
function removeRepeat(o) {
    return o.replace(/([\s\S]{1})(?:\1+)/g,'$1');
}

/**
 * 系统工具类[静态常量和静态方法]
 */
Ext.define("OA.util.AppUtil",{
	alternateClassName: ["OA.AppUtil"],
	requires: ["OA.util.JSLoader"],
	statics: {
	    basePath : window.location.protocol + '//' + window.location.host + '/'
				  + window.location.pathname.split('/')[1] + "/",
	    jsBasePath : window.location.protocol + '//' + window.location.host + '/'
				  + window.location.pathname.split('/')[1] + "/js/",
		imageBasePath : window.location.protocol + '//' + window.location.host + '/'
				  + window.location.pathname.split('/')[1] + "/images/",
		cssBasePath : window.location.protocol + '//' + window.location.host + '/'
				  + window.location.pathname.split('/')[1] + "/css/",
		extjsBasePath : window.location.protocol + '//' + window.location.host + '/'
				  + window.location.pathname.split('/')[1] + "/extjs/",
		extjsThemePath : window.location.protocol + '//' + window.location.host + '/'
				  + window.location.pathname.split('/')[1] + "/extjs/theme/",
		loginPage : window.location.protocol + '//' + window.location.host + '/'
				  + window.location.pathname.split('/')[1] + "/login.jsp",
	    indexPage : window.location.protocol + '//' + window.location.host + '/'
				  + window.location.pathname.split('/')[1] + "/index.jsp",
		loginUrl : window.location.protocol + '//' + window.location.host + '/'
				  + window.location.pathname.split('/')[1] + "/login.do",
		logOutUrl : window.location.protocol + '//' + window.location.host + '/'
				  + window.location.pathname.split('/')[1] + "/logout.do",
		firstTreePanelId: 1,
		/**
		 * ExtJS ajax封装<br/>
		 * 调用示例:
		 * ajax({
		 *       url : "??.do",
		 *       params : {
		 *	        id : "参数值",
		 *	        name: "参数值"
		 *       },
		 *       callback : function(json){}
         *  });
		 * @param {} config
		 */
		ajax : function(config) {
		    Ext.Ajax.request( {
				url : config.url,
				params : config.params,
				method : config.method || 'post',
				callback : function(options, success, response) {
					config.callback(Ext.JSON.decode(response.responseText));
				}
			});
		},
		
		/**
		 * 返回星期几的中文形式
		 * @param {} date
		 * @return {}
		 */
		getDayOfWeek : function(date) {
			var week = [ "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" ];
			return week[day.getDay()];
		},
		
		/**
		 * ExtJS组件的命令空间路径转换成组件的实际访问路径<br/>
		 * 如:OA.view.user.UserPanel转换后basePath + app/view/user/UserPanel.js
		 *     
		 * @param {} np
		 * @return {}
		 */
		namespace2Path : function(np) {
			if(!np) {
			    return null;
			}
			np = np + "";
		    return OA.util.AppUtil.basePath + np.replace(/\./g,"/").replace("OA","app") + ".js";
		},
		
		/**
		 * 用户退出系统
		 */
		logout : function() {
		    Ext.Msg.confirm('提示', "您确认要退出系统吗?", function(btn) {
				if (btn == "yes") {
					OA.util.AppUtil.ajax({
					    url : OA.util.AppUtil.logOutUrl,
					    params : {},
					    callback : function(json){
					        if(json && json.success) {
					            window.location = OA.util.AppUtil.loginPage;
					        }
					    }
					});
				}
			});
		},
		
		/**
		 * 显示当前时间的时钟信息
		 * @param {} domId     时钟信息要显示在哪个dom元素上
		 * @param {} pattern   日期时间显示格式,如yyyy-MM-dd hh:mm:ss
		 */
		showColock : function(domId,pattern) {
		    var date = new Date();
		    var colockEl = Ext.get(domId);
		    if(!colockEl) {
		    	return;
		    }
		    colockEl.dom.innerHTML = date.format(pattern || "yyyy年MM月dd日    hh:mm:ss w");
		},
		
		/**
		 * 动态添加Tab页
		 * @param {} node
		 */
		openPanel: function(node,centerPanelId) {
	        var max = 5;
	        var id = node.data.component || "_tab0";
	        var centerPanel = Ext.getCmp(centerPanelId);
	        var grid = centerPanel.getComponent(node.data.id);
	        if (!grid) {
	            if (this.items && this.items.length >= max) {
	                Ext.Msg.alert("错误", "<span style='font-size:14px;font-weight:600;color:red;'>最多能打开5个模块,请先关闭部分不再使用的模块!</span>");
	            }
	            else {
	            	var tab = {};
	                centerPanel.getEl().mask("正在加载面板,请稍候...");
	                //var cla = Ext.decode("{cla:" + id + "}",true).cla;
	                if(node.data.type == "url") {
            		    tab = Ext.create("Ext.panel.Panel",{
		                    itemId: node.data.id,
		                    xtype: 'panel',
		                    title: node.data.text,
		                    layout: 'fit',
		                    closable: true,
		                    autoScroll: true,
		                    border: true,
		                    autoDestroy : true,
                            closeAction : 'destory',
		                    html: '<iframe width="100%" height="100%" frameborder="0" src="' + id + '"></iframe>'
		                    //iconCls: 'modelIcon'
		            	});
	            	} else if(node.data.type == "component") {
	            		tab = Ext.create("Ext.panel.Panel",{
		                    itemId: node.data.id,
		                    xtype: 'panel',
		                    title: node.data.text,
		                    layout: 'fit',
		                    closable: true,
		                    autoScroll: true,
		                    border: true,
		                    autoDestroy : true,
                            closeAction : 'destory',
		                    items:[
		                    	{xtype: id}
		                    ]
		            	});
	            	}
	                centerPanel.add(tab);
	                centerPanel.setActiveTab(tab);
	                centerPanel.doLayout();
	                centerPanel.getEl().unmask();
	            }
	        }
	        else {
	            centerPanel.setActiveTab(tab);
	            centerPanel.getEl().unmask();
	        }
	    },
	    
	    /**
	     * 动态添加TreePanel
	     */
	    addTreePanel : function(data,leftPanel) {
	        Ext.getBody().unmask();
	        for (var i = 0; i < data.length; i++) {
	        	/*leftPanel.add(Ext.create("OA.view.LeftTreePanel",{
	        		id: data[i].id,
	        		title: data[i].text,
	        	    iconCls: data[i].iconCls
	        	}));*/
	        	leftPanel.add({
	        		xtype: "lefttreepanel",
	        		itemId: data[i].id,
	        		title: data[i].text,
	        	    iconCls: data[i].iconCls
	        	});
	        }
	        leftPanel.doLayout();
	    },
	    /**
	     * 添加手风琴面板
	     * @param {} leftPanelId
	     */
	    addAccordionPanel : function(data,leftPanelId) {
	    	var leftPanel = Ext.getCmp(leftPanelId);
	    	Ext.getBody().unmask();
	        for (var i = 0; i < data.length; i++) {
	        	if(i == 0) {
	        	    leftPanel.add({
		        		xtype: "panel",
		        		itemId: data[i].id,
		        		title: data[i].text,
		        	    iconCls: data[i].iconCls,
		        	    layout: 'fit',
		        	    items: [
			        	    {
			        	    	xtype: "lefttreepanel",
			        	    	root: {
	    							id: data[i].id,
	    							expanded: true
	    						}
			        	    }
		        	    ]
		        	});
	        	} else {
	        		leftPanel.add({
		        		xtype: "panel",
		        		itemId: data[i].id,
		        		title: data[i].text,
		        	    iconCls: data[i].iconCls,
		        	    layout: 'fit'
		        	});
	        	}
	        }
	        leftPanel.updateLayout();
	    },
	    
		/**
		 * 更换皮肤
		 */
		changeTheme: function(itemId, checked) {
		    if (checked) {
		    	var css = OA.util.AppUtil.extjsThemePath;
		        cssname = itemId.replace("Skin-", "").toLowerCase();
		        css += "ext-theme-" + cssname + "/ext-theme-" + (cssname == "default" ? "classic" : cssname) + "-all.css";
		        Ext.util.CSS.swapStyleSheet(null, css);
		        var exp = new Date();
		        //Cookie保存30天
		        exp.setTime(exp.getTime() + 30 * 24 * 60 * 60 * 1000);
		        Ext.util.Cookies.set("ThemeCSS", css, exp);
		        Ext.util.Cookies.set("ThemeName", itemId, exp);
		    }
		}
	}
});

 index.jsp是测试页面

ExtJS5学习之MVC_第2张图片
 demo里也附带了换肤功能实现

ExtJS5学习之MVC_第3张图片
    需要源代码的,请加Q-Q群 105098806

 

 

 

 

你可能感兴趣的:(extjs5)