根据配置文件加载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 相关文章推荐
javascript Prototype 对象扩展
May 15 Javascript
Javascript Math对象
Aug 13 Javascript
javascript实现复选框选中属性
Mar 25 Javascript
客户端验证用户名和密码的方法详解
Jun 16 Javascript
js监听input输入框值的实时变化实例
Jan 26 Javascript
简单实现jquery隔行变色
Nov 09 jQuery
详解React Native 采用Fetch方式发送跨域POST请求
Nov 15 Javascript
webpack项目调试以及独立打包配置文件的方法
Feb 28 Javascript
在react-router4中进行代码拆分的方法(基于webpack)
Mar 08 Javascript
Vue循环中多个input绑定指定v-model实例
Aug 31 Javascript
微信小程序picker组件两列关联使用方式
Oct 27 Javascript
基于js实现的图片拖拽排序源码实例
Nov 04 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
轻松入门: 煮好咖啡的七个诀窍
2021/03/03 冲泡冲煮
php jq jquery getJSON跨域提交数据完整版
2013/09/13 PHP
php快递单号查询接口使用示例
2014/05/05 PHP
Win7下手动安装apache2.2、php5.4笔记
2015/04/03 PHP
Laravel5框架添加自定义辅助函数的方法
2018/08/01 PHP
可以把编码转换成 gb2312编码lib.UTF8toGB2312.js
2007/08/21 Javascript
JavaScript使用技巧精萃[代码非常实用]
2008/11/21 Javascript
js自执行函数的几种不同写法的比较
2012/08/16 Javascript
JQuery中SetTimeOut传参问题探讨
2013/05/10 Javascript
利用了jquery的ajax实现二级联互动菜单
2013/12/02 Javascript
JsRender for index循环索引用法详解
2014/10/31 Javascript
使用JavaScript刷新网页的方法
2015/06/04 Javascript
js跨浏览器的事件侦听器和事件对象的使用方法
2015/12/17 Javascript
使用jQuery5分钟快速搞定双色表格的简单实例
2016/08/08 Javascript
Javascript中的 “&amp;” 和 “|” 详解
2017/02/02 Javascript
layui获取多选框中的值方法
2018/08/15 Javascript
AngularJS $http post 传递参数数据的方法
2018/10/09 Javascript
nodejs中用npm初始化来创建package.json的实例讲解
2018/10/10 NodeJs
详解vue2.0 资源文件assets和static的区别
2018/11/27 Javascript
jQuery动态生成的元素绑定事件操作实例分析
2019/05/04 jQuery
跟老齐学Python之不要红头文件(1)
2014/09/28 Python
在Python中操作列表之List.append()方法的使用
2015/05/20 Python
python Pandas如何对数据集随机抽样
2019/07/29 Python
如何基于python实现画不同品种的樱花树
2020/01/03 Python
用python打开摄像头并把图像传回qq邮箱(Pyinstaller打包)
2020/05/17 Python
Python爬虫之Selenium实现键盘事件
2020/12/04 Python
python中delattr删除对象方法的代码分析
2020/12/15 Python
如何用H5实现一个触屏版的轮播器的实例
2017/01/09 HTML / CSS
交通事故和解协议书
2014/09/25 职场文书
学期个人工作总结
2015/02/13 职场文书
2015应届毕业生求职信范文
2015/03/20 职场文书
国王的演讲观后感
2015/06/03 职场文书
单位考核鉴定意见
2015/06/05 职场文书
PHP 技巧 * SVG 保存为图片(分享图生成)
2021/04/02 PHP
详解JVM系列之内存模型
2021/06/10 Javascript
vue实现省市区联动 element-china-area-data插件
2022/04/22 Vue.js