根据配置文件加载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 相关文章推荐
学习ExtJS(一) 之基础前提
Oct 07 Javascript
json 实例详细说明教程
Oct 31 Javascript
jQuery中绑定事件的命名空间详解
Apr 05 Javascript
Javascript控制页面链接在新窗口打开具体方法
Aug 16 Javascript
JavaScript极简入门教程(二):对象和函数
Oct 25 Javascript
完美兼容多浏览器的js判断图片路径代码汇总
Apr 17 Javascript
基于JavaScript实现移动端TAB触屏切换效果
Oct 20 Javascript
js实现图片轮播效果
Dec 19 Javascript
jQuery 监控键盘一段时间没输入
Apr 22 Javascript
微信小程序 网络API 上传、下载详解
Nov 09 Javascript
Vue中父组件向子组件通信的方法
Jul 11 Javascript
最基础的vue.js双向绑定操作
Aug 23 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
浅析PHP中的字符串编码转换(自动识别原编码)
2013/07/02 PHP
php截取视频指定帧为图片
2016/05/16 PHP
PHP中获取文件创建日期、修改日期、访问时间的方法
2016/11/05 PHP
php in_array() 检查数组中是否存在某个值详解
2016/11/23 PHP
PHP迭代器和迭代的实现与使用方法分析
2018/04/19 PHP
Ajax请求PHP后台接口返回信息的实例代码
2018/08/21 PHP
PHP语言对接抖音快手小红书视频/图片去水印API接口源码
2020/08/11 PHP
Javascript - HTML的request类
2007/01/09 Javascript
javascript代码加载优化方法
2011/01/30 Javascript
取得窗口大小 兼容所有浏览器的js代码
2011/08/09 Javascript
js实现的切换面板实例代码
2013/06/17 Javascript
JavaScript异步编程:异步数据收集的具体方法
2013/08/19 Javascript
javascript获取form里的表单元素的示例代码
2014/02/14 Javascript
JavaScript设计模式之适配器模式介绍
2014/12/28 Javascript
jQuery实现带动画效果的多级下拉菜单代码
2015/09/08 Javascript
JS将滑动门改为选项卡(需鼠标点击)的实现方法
2015/09/27 Javascript
JavaScript中对象的不同创建方法
2016/08/12 Javascript
使用jQuery监听扫码枪输入并禁止手动输入的实现方法(推荐)
2017/03/21 jQuery
js 获取元素的具体样式信息getcss(实例讲解)
2017/07/05 Javascript
Makefile/cmake/node-gyp中区分判断不同平台的方法
2018/12/18 Javascript
配置一个vue3.0项目的完整步骤
2019/04/26 Javascript
微信小程序通过一个json实现分享朋友圈图片
2019/09/03 Javascript
Node.js API详解之 Error模块用法实例分析
2020/05/14 Javascript
vue循环中点击选中再点击取消(单选)的实现
2020/09/10 Javascript
Python多进程同步简单实现代码
2016/04/27 Python
Python字符串和字典相关操作的实例详解
2017/09/23 Python
对Python生成汉字字库文字,以及转换为文字图片的实例详解
2019/01/29 Python
python装饰器常见使用方法分析
2019/06/26 Python
OpenCV+face++实现实时人脸识别解锁功能
2019/08/28 Python
canvas学习笔记之2d画布基础的实现
2019/02/21 HTML / CSS
美国领先的水果篮送货公司和新鲜水果供应商:The Fruit Company
2018/02/13 全球购物
三陽商会官方网站:Sanyo iStore
2019/05/15 全球购物
工作态度恶劣检讨书
2015/05/06 职场文书
MySQL七大JOIN的具体使用
2022/02/28 MySQL
Android开发之WECHAT微信小程序路由跳转的两种形式
2022/04/12 Java/Android
Win11无法安装更新补丁KB3045316怎么办 附KB3045316补丁修复教程
2022/08/14 数码科技