对于一个复杂的系统来说,客户端的JS可能会有上百个,如果全部加载到用户的浏览器中,一方面会导致多余的网络传输,另一方面浏览器解析大量的Js会导致性能下降,这两点都会显著的影响用户可察觉性能。所以对于Js的加载,是动态进行的,这个动态进行表现为两种方式:
- 能不加载的Js就绝不加载。
- 需要加载的Js在直到确实用到的时候才加载。
1,能不加载的Js就绝不加载
拿登陆的流程为例:
尝试登陆包含两种情况,一种是用户刷新页面时,尝试根据当前的令牌自动登陆,另一种是用户在上一次登录时保存了用户名和密码,这两种情况无论哪一种登陆成功了,都不需要用户再次登陆了,从而也就不需要加载FormLogin这个Js了。
2,需要加载的Js在直到确实用到的时候才加载
对于功能模块来说,仅当当前用户具有该模块的权限时,才会生成显示相关的菜单项。而今当该模块的某一个菜单项目第一次被点击时,该模块的相关Js才会被加载:
3,基于ExtJs Ajax的Js加载
ExtJs中的Ajax调用是异步的,而动态加载Js通常意味着在该Js加载完成后调用一个函数,且该函数可能是要加载的Js中的一个函数,所以上图对应的代码应该这样写:
Srims.Action.actions = { 'project-vertical-list': function(){ Srims.Action._callProjectAction('Srims.projects.listVerticalProject();'); }, 'project-horizontal-list': function(){ Srims.Action._callProjectAction('Srims.projects.listHorizontalProject();'); } }; Srims.Action._callProjectAction = function(fn){ if (Srims.projects) { eval(fn); } else { Srims.loadProjectModule(fn); } }
Srims.loadProjectModule = function(callbackFunctionString){ Ext.namespace('Srims.projects'); var js = ["/srims/projects/projectLevel.js"]; js[js.length] = "/srims/projects/projectState.js"; js[js.length] = "/srims/projects/project.js"; js[js.length] = "/srims/projects/projectStore.js"; js[js.length] = "/srims/projects/projectGridPanel.js"; js[js.length] = "/srims/projects/projectAction.js"; Srims.loadJs(js, function(){ eval(callbackFunctionString) }); }
当要执行的函数为要加载的Js中包含的函数时,函数名称当参数传递,加载完毕后,调用eval执行该函数。
真正执行加载操作的是Srims.loadJs这个函数,它接受两个参数:第一个参数是要加载的Js——可以是一个Js,也可以是一个Js数组;第二个参数是加载完毕后的回调函数。当要加载的是一个Js时,加载很简单:发起Ajax请求,对取得的结果用eval执行,然后eval回调函数;当要加载的是一系列Js时(就像上面代码中那样),情况会复杂一点,需要递归的调用loadJs,直到所有Js加载完毕,然后eval回调函数。以下是代码:
1: Srims.JsToLoad = undefined;
2: Srims.JsLoadCallBack = undefined;
3: Srims.loadJs = function(js, callback){
4: Srims.JsToLoad = js;
5: Srims.JsLoadCallBack = callback;
6: Srims._loadJs();
7: }
8: Srims._loadJs = function(){
9: var js = Srims.JsToLoad;
10: var callback = Srims.JsLoadCallBack;
11:
12: if (Ext.type(Srims.JsToLoad) != 'string') {
13: if (Srims.JsToLoad.length == 1) {
14: js = Srims.JsToLoad[0];
15: callback = Srims.JsLoadCallBack;
16: }
17: else {
18: js = Srims.JsToLoad.shift();
19: callback = Srims._loadJs;
20: }
21: }
22:
23: Ext.Ajax.request({
24: url: '/javascript' + js,
25: success: Srims._onLoadJs,
26: method: 'GET',
27: scope: callback
28: });
29: }
30: Srims._onLoadJs = function(response){
31: eval(response.responseText);
32: this();
33: }