extjs版本:4.2.1
在html中添加应用的启动脚本,如下:
<script src="app.js"></script>
2. 用户访问html的时候,会去加载app.js文件,app中定义了应用的名字,根路径等信息,并且调用Ext.application()方法,如下:
Ext.application({ name: 'Seed', extend: 'Seed.Application', autoCreateViewport: true });
3. Ext.application的详解见 http://wangyuelucky.blog.51cto.com/
主要做如下三件事:
设置loader的path
调用Ext.define()
当Ext.onReady的时候,实例化app,代码如下
Ext.onReady(function() { // this won't be called until App has been created and its requires have been // met... Ext.app.Application.instance = new App(); });
4. Ext.define()的详解见 http://wangyuelucky.blog.51cto.com/1011508/1594628
主要是调用Manager.create(),实例化生成新的对象new Class(ctor, data, fn);
其中,var ctor = makeCtor();代码如下:
// Creates a constructor that has nothing extra in its scope chain. function makeCtor () { // 什么作用? 工厂模式? function constructor () { // Opera has some problems returning from a constructor when Dragonfly isn't running. The || null seems to // be sufficient to stop it misbehaving. Known to be required against 10.53, 11.51 and 11.61. return this.constructor.apply(this, arguments) || null; } return constructor; }
另外,这里的Class就是Ext.Class,代码如下:
(function(Class, alias, arraySlice, arrayFrom, global) { var Manager = Ext.ClassManager = { create: function(className, data, createdFn) { // 略 return new Class(ctor, data, /** fn略 */); } }; }(Ext.Class, Ext.Function.alias, Array.prototype.slice, Ext.Array.from, Ext.global));
5.
Ext.Class源码详解http://wangyuelucky.blog.51cto.com/1011508/1594638
Ext.Class相当于是构造函数,主要做两件事:
根据构造器ctor和类的配置信息data,调用ExtClass.create()方法,实例化对象并返回
调用ExtClass.process()方法,执行拦截器
6. ExtClass.create(ctor,data)方法非常简单,就是把基类Ext.Base中的静态属性和方法,都复制到ctor上,并返回ctor
7. ExtClass.process(Class, data, onCreated),会执行三类拦截器className,extend,loader,详解见http://wangyuelucky.blog.51cto.com/1011508/1603157,然后执行ExtClass.onBeforeCreated(ctor,data,hooks) // 这里的hook其实就是拦截器 + 4步中的回调函数fn
这里会处理两件事:
Class.addMembers(data);
hooks.onCreated.call(Class, Class); // 执行4中的回调函数fn
8. 这三类拦截器中,比较复杂的是loader拦截器,详解见http://wangyuelucky.blog.51cto.com/1011508/1603255
主要作用如下:
按关键字查找当前类的所有直接依赖
检查循环依赖
调用Loader.require(dependencies,fn);加载依赖文件
9. Loader.require()方法详解见http://wangyuelucky.blog.51cto.com/1011508/1594617
检查依赖文件是否在例外列表中
如果第8步中的回调方法fn,定义了参数,需要把相关对象的引用传递回去
以dependencies数组的形式,把所有的待加载的依赖信息,放入到队列queue中
调用Loader.loadScriptFile(filePath,onFileLoaded); 加载每一个依赖文件,并且标记待加载的文件数+1
Loader.numPendingFiles++;
10. loadScriptFile()方法,就是对同步/异步加载,做一个判断,如果是异步加载,则调用Loader.injectScriptElement()方法
11. Loader.injectScriptElement()方法,会向html中添加<script>标签,并设置回调文件加载、解析成功的函数为第9步中的onFileLoaded,这样每当加载成功一个文件,就执行onFileLoaded()方法
12. onFileLoaded(className, filePath)方法,其实就是标记文件在Loader中的信息
标记类className已经被加载 isClassFileLoaded[className] =
true
;
标记文件filePath已经被加载 isFileLoaded[filePath] =
true
;
待加载文件数-1 Loader.numPendingFiles--;
处理missingClasses
当待加载文件数等于0,也就是说loader没有待加载的文件的时候,调用Loader.refreshQueue();
13. Loader.refreshQueue(),详解见http://wangyuelucky.blog.51cto.com/1011508/1604695,该方法会检查queue中的每一个对象的每一个依赖项dependence,是否已经被加载、创建Manager.isCreated(requires[j]).
如果已经被创建则删除此依赖项,如果某个对象的所有依赖项都已经被创建,则从queue中移除该对象。
如果队列queue为空,则调用Loader.triggerReady()方法
注:我这里有几个疑问
Loader的待加载数已经为0了,为什么不直接调用Loader.triggerReady()
Loader的待加载数已经为0了,就不会再有文件被加载了,也就不会再执行onFileLoaded和refreshQueue方法了,怎么破?
14. Loader.triggerReady()方法,会调用Loader.require()去加载use关键字依赖项。然后执行第3步中的Ext.onReady
序列图:
创建应用 https://www.websequencediagrams.com/?open=72341
加载文件 https://www.websequencediagrams.com/?open=72348
加载完成回调 https://www.websequencediagrams.com/?open=72453
Ext.onReady https://www.websequencediagrams.com/?open=72343