根据配置文件加载js依赖模块
要求:
根据下面的配置文件
module=[
{'name':'jquery','src':'/js/lib/jquery-1.8.3.js'},
{'name':'swfobject','src':'/js/utils/swfobject.js'},
{'name':'fancybox','src':'/js/jquery/jquery.fancybox.js','require':['jquery']},
{'name':'uploadify','src':'/js/utils/uploadify.js','require':['swfobject']},
{'name':'jqform','src':'/js/jquery/jquery.form.js','require':['jquery']},
{'name':'register','src':'/js/page/reg.js','require':['jqform']},
{'name':'login','src':'/js/page/login.js','require':['fancybox','jqform']},
{'name':'upload','src':'/js/page/upload.js','require':['fancybox','jqform','uploadify']}
]
写一个函数
defgetfiles(name)
返回加载某个name指定的页面,要加载的js文件列表,有依赖的要先加载
小菜解法
此题粗看起来很简单,实则不然。
难点在于依赖模块的加载时机。假如有这样的依赖关系:A-B&C、B-C,A模块依赖B模块和C模块,同时B模块又依赖了C模块,总不能让C加载两次吧!
小菜给出的这个解法,只是一个思路,肯定有比这更好的算法,小菜觉得可以用二叉树之类的算法解决,但小菜不会呀~~~
此算法没有考虑循环依赖的情景。
代码如下:
/**
*不考虑循环依赖
*@type{Function}
*/
varloadModule=(function(){
/**
*业务逻辑封装
*@type{{chainHead:{},chainCurrent:{},srcCache:{},main:main,load:load,findModule:findModule}}
*/
varlogics={
chainHead:{}, //链表头
chainCurrent:{}, //链表当前节点
srcCache:{}, //modulesrc缓存
/**
*对外接口
*@parammodules 配置对象
*@paramname 模块名称
*@returns{Array}依赖模块列表,按照加载先后顺序排列
*/
main:function(modules,name){
varnameArray=[], //模块名称列表
srcArray=[], //依赖模块列表
nameStr="", //模块名称字符串集
repeatRegex=/(^|)([\w]+).*\2/, //模块名称去重正则
i=0;
//粗略加载所有依赖模块
this.load(modules,name)
//构造模块名称字符串集
this.chainCurrent=this.chainHead;
while(this.chainCurrent.next){
nameArray.push(this.chainCurrent.name);
this.chainCurrent=this.chainCurrent.next;
}
nameStr=nameArray.join("")+""; //统一标准,末尾补一个空格
//依赖模块去重
while(repeatRegex.exec(nameStr)){
nameStr=nameStr.replace(repeatRegex,function(g0,g1,g2){
returng0.substring(0,(g0.length-g2.length));
});
}
nameStr=nameStr.substring(0,(nameStr.length-1)); //去掉补充的多余空格
//依赖模块名称转换为模块路径
nameArray=nameStr.split("");
for(i=0;i<nameArray.length;i++){
srcArray.push(this.srcCache[nameArray[i]]);
}
returnsrcArray;
},
/**
*递归加载模块
*@parammodules 配置对象
*@paramname 模块名称
*/
load:function(modules,name){
varnode={},
module=this.findModule.call(modules,"name",name),
i=0;
//判断模块是否存在
if(!module){
throwError("依赖模块"+name+"未找到");
}
//构造模块依赖链表
node.name=name;
// node.src=module.src;
this.srcCache[name]=module.src;
node.next=this.chainHead;
this.chainHead=node;
//递归依赖
if(module.require&&module.require.length){
for(i=0;i<module.require.length;i++){
this.load(modules,module.require[i]);
}
}
},
/**
*根据指定属性名称和属性值查找模块
*@paramname 属性名称
*@paramvalue 属性值
*@returns{*}
*/
findModule:function(name,value){
vararray=this,
item={},
i=0;
//遍历模块
for(i=0;i<array.length;i++){
item=array[i];
//获取指定模块
if(item&&item[name]===value){
returnitem;
}
}
//找不到返回null
returnnull;
}
};
//暴露对外接口
returnfunction(){
returnlogics.main.apply(logics,arguments);
};
}());
/**
*TestUsecase
*@type{*[]}
*/
varmodules=[
{'name':'jquery','src':'/js/lib/jquery-1.8.3.js'},
{'name':'swfobject','src':'/js/utils/swfobject.js'},
{'name':'fancybox','src':'/js/jquery/jquery.fancybox.js','require':['jquery']},
{'name':'uploadify','src':'/js/utils/uploadify.js','require':['swfobject']},
{'name':'jqform','src':'/js/jquery/jquery.form.js','require':['jquery']},
{'name':'register','src':'/js/page/reg.js','require':['jqform']},
{'name':'login','src':'/js/page/login.js','require':['fancybox','jqform']},
{'name':'upload','src':'/js/page/upload.js','require':['fancybox','jqform','login','uploadify']}
];
console.log(loadModule(modules,"upload"));