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

 更新时间:2014年12月29日 10:52:29   投稿:hebedich  
这篇文章主要介绍了根据配置文件加载js依赖模块,解决方法是笔者自己的思路,抛砖引玉,需要的朋友可以参考下

要求:

根据下面的配置文件

复制代码 代码如下:

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"));

相关文章

  • js实现带关闭按钮始终显示在网页最底部工具条的方法

    js实现带关闭按钮始终显示在网页最底部工具条的方法

    这篇文章主要介绍了js实现带关闭按钮始终显示在网页最底部工具条的方法,是非常实用的javascript固定效果,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-03-03
  • 使用Promise链式调用解决多个异步回调的问题

    使用Promise链式调用解决多个异步回调的问题

    这篇文章主要给大家介绍了使用Promise链式调用解决多个异步回调问题的方法,文中给出了详细的介绍和示例代码,有需要的朋友可以参考借鉴,下面来一起学习学习吧。
    2017-01-01
  • 小程序两种滚动公告栏的实现方法

    小程序两种滚动公告栏的实现方法

    这篇文章主要介绍了小程序两种滚动公告栏的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • JavaScript 编写匿名函数的几种方法

    JavaScript 编写匿名函数的几种方法

    匿名函数可以有效控制变量作用域,构造闭包 (Closure),防止对全局变量造成污染。在 JavaScript 中,编写匿名函数,有以下几种方法.
    2010-02-02
  • jstree的简单实例

    jstree的简单实例

    最近使用到了jstree,感觉是一款灵活的、可多项定制的tree插件。下面通过本文给大家详细介绍下jstree的简单实例,需要的朋友可以参考下
    2016-12-12
  • javascript中this用法实例详解

    javascript中this用法实例详解

    这篇文章主要介绍了javascript中this用法,结合具体实例形式详细分析了javascript中this的含义及对象、函数等各种调用中的使用技巧,需要的朋友可以参考下
    2017-04-04
  • javascript 文档的编码问题解决

    javascript 文档的编码问题解决

    在引用与本页面编码格式不一样的js文档时,如果被引用的js代码有ASCII字符之外的字符,那么就会出现代码错误。
    2009-03-03
  • JavaScript 面向对象程序设计详解【类的创建、实例对象、构造函数、原型等】

    JavaScript 面向对象程序设计详解【类的创建、实例对象、构造函数、原型等】

    这篇文章主要介绍了JavaScript 面向对象程序设计,结合具体实例形式详细分析了JavaScript面向对象程序设计中类的创建、实例对象、构造函数、原型等相关概念、原理、用法及操作注意事项,需要的朋友可以参考下
    2020-05-05
  • 原生js实现宽度计数器

    原生js实现宽度计数器

    这篇文章主要为大家详细介绍了原生js实现宽度计数器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09
  • 轻松理解JavaScript之AJAX

    轻松理解JavaScript之AJAX

    本文主要介绍了JavaScript中的AJAX的相关知识,具有很好的参考价值,下面跟着小编一起来看下吧
    2017-03-03

最新评论