在Extjs中,为了满足动态加载js文件的过程,经过本人测试,可采用以下两种方式:
1、在一个application实例下
在此情况下,可采用Ext.require()函数进行动态按需加载js文件。以加载一个controller为例:
Ext.require('MyApp.controller.event.Bases',function(){
MyApp.getController('event.Bases').init();
tab = me.getTabpanel().add({
xtype: view,
closable: true,
animate : true,
iconCls: 'icon-rights',
title: record.raw.menuName
});
此controller为MyApp.controller.event.Bases,在才用Ext.require()加载指定文件时,只会通过网络获取此文件,即
MyApp.controller.event.Bases.js文件,此时并未加载controller所依赖的model,store,view,此时还需要调用
MyApp.getControoler()方法对所获得的controller文件进行初始化,调用其init()方法将加载所依赖的store,model和view文件。另外,
通过查看Ext.app.Application的getController源码:
getController: function(name) {
var me = this,
controllers = me.controllers,
className, controller;
controller = controllers.get(name);
if (!controller) {
className = me.getModuleClassName(name, 'controller');
controller = Ext.create(className, {
application: me,
id: name
});
controllers.add(controller);
if (me._initialized) {
controller.doInit(me);
}
}
return controller;
},
通过阅读getController文件源码,可看出:通过getController方法,首先获得对应controller对应controller的className,然后通过Ext.create()
方法创建controller,并将此controller加入到对应MyApp实例的controllers中,最重要的一点,然后调用controller.doInit()方法初始化controler,
加载对应的store,model,view文件以及调用init()方法,所以在单application下,可以简化动态加载过程:
MyApp.getController('event.Bases').init();
为使Ext.Loader动态加载开启,需进行如下设置:
Ext.Loader.setConfig({
enabled : true
});
2、多实例application
首先以ExtJs 4.1版本进行测试,在大系统下,可对业务进行模块划分,各个模块可以单独创建application,当需要加载指定模块时,创建对应的
application,并加载其依赖文件,实现各个模块的按需加载,相比一次性加载所有文件相比,系统的启动加载速度将提高。
在加载各个模块时,可以才用loader属性或者加载iframe完成,在iframe用法中将会重复加载文件,这里不予介绍,下面主要介绍一下loader
方法。 在ExtJs4.1 版本下,假定左边为treepanel,右边为tabpanel,点击左边的树节点将分模块加载对应的application,并在右侧的tabpanel
中进行显示,当点击左侧树节点时,在其点击相应函数中添加:
panel = tab.add(Ext.create('Ext.panel.Panel', {
id : record.raw.id,
title : record.raw.text,
layout : 'fit',
loader : {
url : record.raw.url,
autoLoad : true,
scripts : true
},
autoShow : true,
autoRender : true,
tabTip : record.raw.text,
border : false,
renderTo : Ext.getBody(),
closable : true
}));
在loader属性中,url为指定加载的html文件,如app/logApp/logList.html,在此html中引用此模块对应的js文件,其格式如下:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
</head>
<script type="text/javascript" src="app/logApp/logListApp1.js"></script>
<body>
<div id="logpanel"></div>
</body>
</html>
在html中增加<div>标签,作用是将此模块创建的页面渲染到此标签上,下面将会讲到,如果没有此标签,页面将无法渲染,而且在一个系统下,
各模块的<div>的id必须为唯一。html所引用的js文件实例如下:
Ext.Loader.setConfig({
enabled : true
});
Ext.application( {
name : 'LogListApp',
appFolder : 'app/logApp',
autoCreateViewport : false,
controllers : [ 'log.LogInfos'
],
launch : function() {
console.log('logListApp launch!');
Ext.create('Ext.panel.Panel', {
// html: '<p>World!</p>',
renderTo: 'logpanel',
items:[{
xtype: 'loginfolist'
}]
});
}
});
这此文件中创建application,然后引用对于对应controller,以及创建页面,通过renderTo将页面渲染到<div>标签中,在ExtJs 4.1中可以采用
Ext.create的方式创建app,MyApp作为全局application实例变量(命名空间),但在ExtJs4.1 中将存在一个严重问题:新application的创建
将覆盖以前application注册的事件监听,监听失效,这将是毁灭性的。通过测试,有两种解决办法:
(1)、修改注册监听的注册方式
原事件注册方式可能如下:
this.control({
'viewport navigatorheader button[action=login]': {
click: this.login
)
修改注册方式如下:
'viewport':{
render: function(view){
view.down('navigatorheader button[action=login]').on('click',this.login);
}}
将页面事件全部注册到render的相应函数中,这样在ExtJs4.1版本下,各个模块的事件将依然有效。
(2)、引用ExtJs 4.2 版本
事件失效可能是ExtJs4.1版本下的一个bug,在引用4.2版本后,无需修改事件的注册方式即可使用,但application的创建方式放生改变,
如果还是调用Ext.create('Ext.app.applicaton',{})方式无法实例化application ,需要改变其创建方式,在4.2版本的文档中推荐如下方式进行创建:
Ext.application({
name: 'MyApp',
launch: function() {
Ext.create('Ext.container.Viewport', {
items: {
html: 'My App'
}
});
}
});
那么通过如下方法可以获得对应的application 实例:
var app = MyApp.getApplication();
到此为止,就介绍完多app的下的动态加载问题。
可能存在问题:
1、如果各个模块间不存在关联关系,没有相互应用,多app模式下动态加载应该没有问题。
2、如果各个模块间存在关联关系,有相互的引用,那么在一个模块中引用另一模块变量,由于未加载对应的文件,将无法应用,出现错误,
通过Ext.require()加载部分所需文件,这种方式也不可取,还需寻找更好的的解决办法。