Posted in Javascript onDecember 29, 2014
要求:
根据下面的配置文件
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']} ]
写一个函数
def getfiles(name)
返回 加载某个name指定的页面,要加载的js文件列表,有依赖的要先加载
小菜解法
此题粗看起来很简单,实则不然。
难点在于依赖模块的加载时机。假如有这样的依赖关系:A-B&C、B-C,A模块依赖B模块和C模块,同时B模块又依赖了C模块,总不能让C加载两次吧!
小菜给出的这个解法,只是一个思路,肯定有比这更好的算法,小菜觉得可以用二叉树之类的算法解决,但小菜不会呀~~~
此算法没有考虑循环依赖的情景。
代码如下:
/** * 不考虑循环依赖 * @type {Function} */ var loadModule = (function(){ /** * 业务逻辑封装 * @type {{chainHead: {}, chainCurrent: {}, srcCache: {}, main: main, load: load, findModule: findModule}} */ var logics = { chainHead: {}, //链表头 chainCurrent: {}, //链表当前节点 srcCache: {}, //module src 缓存 /** * 对外接口 * @param modules 配置对象 * @param name 模块名称 * @returns {Array} 依赖模块列表,按照加载先后顺序排列 */ main: function(modules, name){ var nameArray = [], //模块名称列表 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){ return g0.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]]); } return srcArray; }, /** * 递归加载模块 * @param modules 配置对象 * @param name 模块名称 */ load: function(modules, name){ var node = {}, module = this.findModule.call(modules, "name", name), i = 0; //判断模块是否存在 if(!module){ throw Error("依赖模块 " + 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]); } } }, /** * 根据指定属性名称和属性值查找模块 * @param name 属性名称 * @param value 属性值 * @returns {*} */ findModule: function(name, value){ var array = this, item = {}, i = 0; //遍历模块 for(i = 0; i < array.length; i++){ item = array[i]; //获取指定模块 if(item && item[name] === value){ return item; } } //找不到返回null return null; } }; //暴露对外接口 return function(){ return logics.main.apply(logics, arguments); }; }()); /** * Test Usecase * @type {*[]} */ var modules=[ {'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"));
根据配置文件加载js依赖模块
- Author -
hebedich声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@