根据配置文件加载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 相关文章推荐
Span元素的width属性无效果原因及解决方案
Jan 15 Javascript
在IE6下发生Internet Explorer cannot open the Internet site错误
Jun 21 Javascript
jquery关于页面焦点的定位(文本框获取焦点时改变样式 )
Sep 10 Javascript
Extjs优化(二)Form表单提交通用实现
Apr 15 Javascript
封装好的js判断操作系统与浏览器代码分享
Jan 09 Javascript
JavaScript高仿支付宝倒计时页面及代码实现
Oct 21 Javascript
JS公共小方法之判断对象是否为domElement的实例
Nov 25 Javascript
jQury Ajax使用Token验证身份实例代码
Sep 22 Javascript
原生JS实现DOM加载完成马上执行JS代码的方法
Sep 07 Javascript
JS实现图片轮播效果实例详解【可自动和手动】
Apr 04 Javascript
JS计算两个数组的交集、差集、并集、补集(多种实现方式)
May 21 Javascript
Vue通过for循环随机生成不同的颜色或随机数的实例
Nov 09 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
thinkphp四种url访问方式详解
2014/11/28 PHP
关于Blog顶部的滚动导航条代码
2006/09/25 Javascript
JavaScript中的property和attribute介绍
2011/12/26 Javascript
javaScript让文本框内的最后一个文字的后面获得焦点实现代码
2013/01/06 Javascript
把jquery 的dialog和ztree结合实现步骤
2013/08/02 Javascript
js showModalDialog参数的使用详解
2014/01/07 Javascript
angularJS结合canvas画图例子
2015/02/09 Javascript
jQuery中常用的遍历函数用法实例总结
2015/09/01 Javascript
js带缩略图的图片轮播效果代码分享
2015/09/14 Javascript
详解Angularjs filter过滤器
2016/02/06 Javascript
js实现select二级联动下拉菜单
2020/04/17 Javascript
第一次接触Bootstrap框架
2016/10/24 Javascript
JavaScript严格模式详解
2017/01/16 Javascript
jQuery实现的动态文字变化输出效果示例【附演示与demo源码下载】
2017/03/24 jQuery
微信小程序Redux绑定实例详解
2017/06/07 Javascript
使用node打造自己的命令行工具方法教程
2018/03/26 Javascript
vue router+vuex实现首页登录验证判断逻辑
2018/05/17 Javascript
详解easyui基于 layui.laydate日期扩展组件
2018/07/18 Javascript
js函数和this用法实例分析
2020/03/13 Javascript
vue 子组件和父组件传值的示例
2020/09/11 Javascript
如何基于viewport vm适配移动端页面
2020/11/13 Javascript
vue脚手架项目创建步骤详解
2021/03/02 Vue.js
[00:14]PWL:老朋友Mushi拍VLOG与中国玩家问好
2020/11/04 DOTA
python备份文件的脚本
2008/08/11 Python
使用Python的turtle模块画图的方法
2017/11/15 Python
python binascii 进制转换实例
2019/06/12 Python
Python代码使用 Pyftpdlib实现FTP服务器功能
2019/07/22 Python
HTML5 Canvas API中drawImage()方法的使用实例
2016/03/25 HTML / CSS
卡骆驰英国官网:Crocs英国
2019/08/22 全球购物
护理专业本科生自荐信
2013/10/01 职场文书
模具专业毕业生自荐书范文
2014/02/19 职场文书
梅花魂教学反思
2014/04/25 职场文书
初级党校心得体会
2014/09/11 职场文书
心灵点滴观后感
2015/06/02 职场文书
入党介绍人意见怎么写
2015/06/03 职场文书
详解Java实践之适配器模式
2021/06/18 Java/Android