根据配置文件加载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函数this的用法实例分析
Feb 05 Javascript
jquery实现可旋转可拖拽的文字效果代码
Jan 27 Javascript
js友好的时间返回函数
Aug 24 Javascript
利用JS屏蔽页面中的Enter按键提交表单的方法
Nov 25 Javascript
微信小程序页面滑动屏幕加载数据效果
Nov 16 Javascript
js移动端图片压缩上传功能
Aug 18 Javascript
js运算符的一些特殊用法
Jul 29 Javascript
在Vant的基础上封装下拉日期控件的代码示例
Dec 05 Javascript
JS实现在线ps功能详解
Jul 31 Javascript
使用Vue.js中的过滤器实现幂方求值的方法
Aug 27 Javascript
Vue+ElementUI使用vue-pdf实现预览功能
Nov 26 Javascript
JavaScript实现简易聊天对话框(加滚动条)
Feb 10 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
杏林同学录(五)
2006/10/09 PHP
Gregarius中文日期格式问题解决办法
2008/04/22 PHP
PHP移动文件指针ftell()、fseek()、rewind()函数总结
2014/11/18 PHP
Zend Framework教程之请求对象的封装Zend_Controller_Request实例详解
2016/03/07 PHP
解决laravel id非自增 模型取回为0 的问题
2019/10/11 PHP
CSS+Table图文混排中实现文本自适应图片宽度(超简单+跨所有浏览器)
2009/02/14 Javascript
jQuery 剧场版 你必须知道的javascript
2009/05/27 Javascript
jQuery 判断页面元素是否存在的代码
2009/08/14 Javascript
jQuery中append()方法用法实例
2014/12/25 Javascript
JS 作用域与作用域链详解
2015/04/07 Javascript
JS事件添加和移出的兼容写法示例
2016/06/20 Javascript
后端接收不到AngularJs中$http.post发送的数据原因分析及解决办法
2016/07/05 Javascript
关于Jquery中的bind(),on()绑定事件方式总结
2016/10/26 Javascript
JavaScript交换两个变量值的七种解决方案
2016/12/01 Javascript
基于jQuery实现的幻灯图片切换
2016/12/02 Javascript
bootstrap提示标签、提示框实现代码
2016/12/28 Javascript
js中数组插入、删除元素操作的方法
2017/02/15 Javascript
微信小程序视图template模板引用的实例详解
2017/09/20 Javascript
微信小程序中button组件的边框设置的实例详解
2017/09/27 Javascript
实例详解vue中的$root和$parent
2019/04/29 Javascript
vue从后台渲染文章列表以及根据id跳转文章详情详解
2020/12/14 Vue.js
numpy实现合并多维矩阵、list的扩展方法
2018/05/08 Python
python创建子类的方法分析
2019/11/28 Python
Python查找不限层级Json数据中某个key或者value的路径方式
2020/02/27 Python
python3发送request请求及查看返回结果实例
2020/04/30 Python
详解Python 函数参数的拆解
2020/09/02 Python
html5中的一些标签学习(心得)
2016/10/18 HTML / CSS
JD Sports荷兰:英国领先的运动时尚零售商
2020/03/13 全球购物
公司领导班子四风对照检查材料
2014/09/27 职场文书
国庆庆典邀请函
2015/02/02 职场文书
慰问信格式
2015/02/14 职场文书
团结主题班会
2015/08/13 职场文书
2019年“我为祖国点赞”演讲稿(3篇)
2019/09/26 职场文书
Python基础之字符串格式化详解
2021/04/21 Python
「海贼王」112.9万粉丝纪念图标公布
2022/03/21 日漫
关于Python中进度条的六个实用技巧分享
2022/04/05 Python