onpageload.js是首页加载的第一个js文件,该文件主要内容为初始化window.Tatami,并在window.Tatami上定义了三个属性:load,require,onpageload。
onpageload
在main.js调用Tatami.onpageload初始化页面,主要传递的参数opts及含义为:
default_url //默认加载模块
before_load //模块加载前处理函数
on_load //当读取时的操作
call_keys //被哪些词呼起会起反应
local_data_keys //需要获得的一些关键字,表达方式为 ‘search_user::local_user’
resources //需要加载的资源列表
complete //当模板加载都完成时
timeout //是否超时之后提醒
func_timeout //超时之后的操作流程
**onpageload init的处理主要为**
1. 检测是否是否设置了初始模块,没有的话返回
2. 超时处理
3. 检测是否需要初始化模块(链接里是否带了模块参数)
如果需要:
- 根据local_data_keys设置session (不过好像项目并没有用到这个字段来设置session)
- pageUrlInit => pageJumpCalc (这边是个针对call_keys的处理) 如果有的话根据配置呼起新的页面,没有的话返回初始模块
呼起方法及配置:
如果call_keys配置为
{'testJump':'http://www.baidu.com/{{userId}}'}
则检测到url testJump时,会将'http://www.baidu.com/{{userId}}'的userId在search里找到对应的值(就是url里&userId=xxxx&,把xxxx找出来替代{{userId}}),然后跳转到'http://www.baidu.com/xxxx'
不过目前没有发现call_keys在项目里的应用。
4. _afterHashchange 主要加载处理
分别把on_load,resources,complete推到任务队列里。如果是resources的话会用到rc.load,一会再讲。
**任务列表的处理为:**
missionStart => 检测是否已经在执行(_isMissionStart),是的话返回,否则_isMissionStart = true => _missionNext: 如果任务列表空了,返回,否则从中拿出一个任务 cur_m = this._missions.shift(),执行并且将超时处理和_missionNext放在cur_m回调里
因为各模块代码在ttm w模式下直接全部加进首页,所以 onpageload 里opts.resources为[],会直接执行complete里面的内容:(Tatami.init 和一些 sub,pub)并没有用到rc.load,但是ttm d后代码是按需加载,会通过rc.load加载。
load 处理资源加载
上面我们知道,onpageload init时会把配置的on_load,resources,complete放到任务列表里,对于on_load和complete执行相应函数就行了,对于resources则会用到rc.load.require(),所以下面我们讲的require的场景都预设从resources处理这边调过来的,require中的func为超时处理和_missionNext
require:入口函数,设置请求过期时间this._timeout;会判断参数中resources需要请求的是单个地址或还是地址数组,这边根据不同情况分为两个处理 —— 单个地址:_require;地址数组:_loadResouce
_require:
1. 先从资源列表(_resList)获得对应资源的状态(资源有三种状态: adding 加载中/complete 加载完成/error 加载失败)
2. 如果已经在资源列表中了,那么对应三种状态分别处理:adding 设置一个周期为1000ms的setInterval,作用为每秒检查一次是否加载完成,如果超过设置的过期时间this._timeout,则执行回调并返回timeout状态码;complete 执行回调 状态码为null ;error 执行回调 状态码为error ;并且return掉 不执行以下操作
3. 如果没有在资源列表中,那么在资源列表中创建状态为adding的对应资源
4. 通过this._getDocObj获取head(避免重复dom获取)
5. 判断资源类型 js/css
6. 根据资源类型创建script/link的node节点
7. 如果资源为css 不考虑加载时间,直接将资源列表(_resList)对应资源状态改为complete
8. 如果资源为js 会判断老IE和webkit分别给onreadystatechange和onload绑定事件:确认加载完成后将对应资源状态改为complete,执行传入的回调
9. 将此link/script加进head里
_loadResouce:
*从3开始是ttm build造出来之前最原始的应用场景,目前ttm build已将该部分工作做掉了,所以2以后的逻辑已经用不到了,感兴趣的可以看下
1. 获取一个经过处理的包含了各依赖信息的资源对象(o_resource)
2. 通过o_resource断该资源组是否存在依赖关系,如果不存在的话,设置一个fn_step回调函数传入_require, 参考(_require第8步),每个资源加载完成时都会执行该回调以为判断资源数组是否加载完,加载完的话执行rc.load.require()时传入的回调(超时处理和_missionNext)
3. 如果存在依赖关系:
根据代码还原了下存在依赖关系的resource结构:
1
2
3
4
5
6
[{
"depend": [
"https://g.alicdn.com/sj/lib/jquery.min.js"
],
"path": "/newIndex/base-333c57afef.js"
}]
那么获取到的资源对象是这样的结构 ——
是否里面有存在依赖的资源(has_depend):true;
存在依赖的资源(o_depend): 以path为key,value为对应整个对象的结构;
没有被依赖的资源(o_undepend):这边会去做一个处理,除了本身不存在depend的数组元素外,还会去分析存在依赖的资源depend的js,如果该js不在o_depend的key中(该js不存在依赖),并且不在resource内(不在o_undepend内),那么会把它加进o_undepend内;
以及没有被依赖的资源的数量(n_undepend),存在依赖的资源的数量(n_depend)
4. 设置fn_step,和不存在依赖的resourse的fn_step的区别在于,这边每加载一条不存在依赖的资源,都会将o_undepend对应的资源状态改为is_load = true;全部o_undepend资源加载完成后,会调用fn_next
5. fn_next: 确认o_undepend资源加载完成后,将依赖资源从o_depend表中删除,_require加载完成后放到o_undepend内,o_depend内所有资源加载完后执行next(超时处理和_missionNext)
6. 循环o_resource.o_undepend,this._require(i, fn_step);
除了在加载opts.resources中会用到rc.load.require,模块载入时也会用到,这边稍微讲一下。当切换模块时:
this.domEvtBind(window, ‘hashchange’, this.proxy(this._pubDomEvtHashchange, this));
当hashchange时,框架会触发_pubDomEvtHashchange
_pubDomEvtHashchange: pub EVENTS.HASHCHANGE
rc.sub(‘EVENTS.HASHCHANGE’, this._hashchange, this) 调用this._hashchange
this._hashchange : this._doPagechangeAct(hash, false, url);
_doPagechangeAct: 这边做了很多事情,具体下次结合rc.pages一起讲;这里只需要知道它触发了MODULES.ROOTLOAD这个事件
MODULES.ROOTLOAD: rootMdulLoad,最终主要的处理都在rootMdulLoad里。首先会根据this.getMdul判断资源是否已经加载在this._mdulList里了(ttm w模式会默认加载了全部js),如果加载过了直接loadMdul,updateMdul这些;否则从_asyncMdulMap找到相应模块对应需加载的资源,通过rc.load.require加载,并传入回调函数funcAct;
以上就是Tatami.onpageload.js代码粗解和部分应用场景,如有补充,欢迎留言。