根据配置文件加载js依赖模块


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"));
Javascript 相关文章推荐
js控制滚动条缓慢滚动到顶部实现代码
Mar 20 Javascript
javascript 原型链维护和继承详解
Nov 26 Javascript
jquery实现带渐变淡入淡出并向右依次展开的多级菜单效果实例
Aug 22 Javascript
向JavaScript的数组中添加元素的方法小结
Oct 24 Javascript
用JavaScript做简易的购物车的代码示例
Oct 20 Javascript
获取本机IP地址的实例(JavaScript / Node.js)
Nov 24 Javascript
Angular4 ElementRef的应用
Feb 26 Javascript
微信小程序实现美团菜单
Jun 06 Javascript
深入学习JavaScript 高阶函数
Jun 11 Javascript
vue prop传值类型检验方式
Jul 30 Javascript
Vue v-for中的 input 或 select的值发生改变时触发事件操作
Aug 31 Javascript
vue封装自定义指令之动态显示title操作(溢出显示,不溢出不显示)
Nov 12 Javascript
JavaScript中的console.dir()函数介绍
Dec 29 #Javascript
JavaScript中的console.group()函数详细介绍
Dec 29 #Javascript
小米公司JavaScript面试题
Dec 29 #Javascript
谷歌浏览器调试JavaScript小技巧
Dec 29 #Javascript
JavaScript中的console.trace()函数介绍
Dec 29 #Javascript
JavaScript中的console.profile()函数详细介绍
Dec 29 #Javascript
jQuery中element选择器用法实例
Dec 29 #Javascript
You might like
De facto standard 世界上不可思议的事实标准
2010/08/29 Javascript
很棒的学习jQuery的12个网站推荐
2011/04/28 Javascript
JQuery插件Style定制化方法的分析与比较
2012/05/03 Javascript
防止浏览器记住用户名及密码的简单实用方法
2013/04/22 Javascript
原生javascript实现拖动元素示例代码
2014/09/01 Javascript
js QQ客服悬浮效果实现代码
2014/12/12 Javascript
使用Raygun对Node.js应用进行错误处理的方法
2015/06/23 Javascript
理解javascript定时器中的单线程
2016/02/23 Javascript
jQuery插件cxSelect多级联动下拉菜单实例解析
2016/06/24 Javascript
浅谈JavaScript 覆盖原型以及更改原型
2016/08/31 Javascript
Vue iview-admin框架二级菜单改为三级菜单的方法
2018/07/03 Javascript
jQuery扩展方法实现Form表单与Json互相转换的实例代码
2018/09/05 jQuery
jQuery实现文本显示一段时间后隐藏的方法分析
2019/06/20 jQuery
[01:11:10]2014 DOTA2华西杯精英邀请赛 5 24 iG VS VG加赛
2014/05/26 DOTA
Python中在for循环中嵌套使用if和else语句的技巧
2016/06/20 Python
用python做一个搜索引擎(Pylucene)的实例代码
2017/07/05 Python
python实现求解列表中元素的排列和组合问题
2018/03/15 Python
python五子棋游戏的设计与实现
2019/06/18 Python
python logging添加filter教程
2019/12/24 Python
python 中不同包 类 方法 之间的调用详解
2020/03/09 Python
django中url映射规则和服务端响应顺序的实现
2020/04/02 Python
python的Jenkins接口调用方式
2020/05/12 Python
python编写一个会算账的脚本的示例代码
2020/06/02 Python
Python实现爬取并分析电商评论
2020/06/19 Python
CSS3实现曲线阴影和翘边阴影
2016/05/03 HTML / CSS
20佳惊艳的HTML5应用程序示例分享
2011/05/03 HTML / CSS
介绍一下内联、左联、右联
2013/12/31 面试题
学生个人求职自荐信格式
2013/09/23 职场文书
生产车间班组长岗位职责
2014/01/06 职场文书
应用化学专业职业生涯规划书
2014/01/22 职场文书
2015年银行柜员工作总结报告
2015/04/01 职场文书
家庭经济困难证明
2015/06/23 职场文书
公司费用报销管理制度
2015/08/04 职场文书
大学生如何逃脱“毕业季创业队即散伙”魔咒?
2019/08/19 职场文书
python中if和elif的区别介绍
2021/11/07 Python
python如何将mat文件转为png
2022/07/15 Python