好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

关于js模块加载的尝试

关于js模块加载的尝试

关于js模块加载的尝试

看了sea.js、requireJs那么完善的模块加载框架,今天尝试来自己写一下简单的加载功能,仅当作为自己学习练习,有很多考虑不周的地方请指出,主要就两个方法:

VM.define(‘模块名称’,{url:‘模块路径’,requires:‘模块依赖项’(可以是模块名的字符串,或者数组)});  

VM.use(‘模块名称’,‘回调函数callback’);

一个是定义模块,一个是使用模块;使用的模块都必须先定义,

定义的时候不会加载模块,只有在使用的时候才加载模块;

1、不会出现重复加载的模块,调用过的模块不会再append第二次,不能定义相同名字的模块;

2、依赖项可以是多个,从左到右加载,多个的时候用数组传参,单个时可以用字符串传参;

3、支持链式调用,要避免循环依赖的情况;

修改:上次的代码存在考虑不周的情况,多谢园友  程序猿小卡   留言的指出,现再的也可能有问题,但是如果正常使用依赖,相信还是能够满足的,仅供研究:)

代码如下: 使用方法:只需引入myModule.js文件, <script type="text/javascript" src="myModule.js"></script>

myModule.js代码如下:

   1   /*  *
    2  
   3    * Author : vvg
    4  
   5    * version : 0.1.1
    6  
   7    * name : VModule.js
    8  
   9    *  */ 
  10  
  11  ( function   () {
   12       //   调试提示 
  13       var  log =  function   (content) {
   14           if  ( typeof  console.log === 'function' ) {
   15               console.log(content);
   16          }  else   {
   17               alert(content);
   18           }
   19       }
   20  
  21       var  createScript =  function   (url) {
   22           var  script = document.createElement('script' );
   23          script.type = 'text/javascript' ;
   24          script.src =  url;
   25           return   script;
   26       };
   27  
  28       var  head = document.getElementsByTagName('head')[0 ];
   29       var  toString =  Object.prototype.toString;
   30  
  31       var  VModule =  {};
   32       /*  *
   33        * 定义模块
   34        * @param name  {string}
   35        * @param options {object}  url/requires
   36        */ 
  37      VModule.define =  function   (name, options) {
   38           //  定义模块名称、地址和依赖 
  39           if  (! this .modules)  this .modules =  {};
   40           if  ( this  .modules[name]) {
   41              log(name + '已经存在,请更换名称.' );
   42               return  ;
   43           }
   44           this .modules[name] =  options;
   45           //   是否加载 
  46           this .modules[name].isLoad =  false  ;
   47           //   是否使用 
  48           this .modules[name].isUse =  false  ;
   49           //   回调队列 
  50           this .modules[name].callBackQueue =  [];
   51           return   this  ;
   52       }
   53  
  54      VModule.use =  function   (name, func) {
   55           var  len, self =  this  ;
   56           if  (! this  .modules[name]) {
   57              log(name + '不存在.' );
   58               return   this  ;
   59           }
   60           //   回调队列,用于多次use同一个模块时的多个回调 
  61           var  callBackQueue =  this  .modules[name].callBackQueue;
   62           if  (! this  .modules[name].isUse) {
   63               //   标记模块已经使用过 
  64               this .modules[name].isUse =  true  ;
   65               //   推入队列 
  66               callBackQueue.push(func);
   67               var  url =  this  .modules[name].url;
   68               var  requires =  this  .modules[name].requires;
   69  
  70               //   串行依赖情况 
  71               if  (toString.call(requires) == '[object String]' ) {
   72                   this .use(requires,  function   () {
   73                       self.load(name, callBackQueue);
   74                   });
   75                   return   this  ;
   76               }
   77  
  78               //   并行依赖处理 
  79               if  (toString.call(requires) == '[object Array]' ) {
   80                   //  循环查找 
  81                  len =  requires.length;
   82                   this .modules[name].count =  len;
   83                   for  ( var  i = 0; i < len; i++ ) {
   84                       var  self =  this  ;
   85                       this .use(requires[i],  function   () {
   86                          VModule.modules[name].count-- ;
   87                           //   串行依赖即等待所有的文件加载完毕后才执行回调 
  88                           if  (VModule.modules[name].count == 0 ) {
   89                               self.load(name,callBackQueue);
   90                           }
   91                       })
   92                   }
   93                   return   this  ;
   94               }
   95               this  .load(name, callBackQueue);
   96          }  else   {
   97               //   如果模块已经标记使用,但是模块还未下载完毕时,加入队列, 如果下载完毕则直接执行回调函数 
  98               if (! this  .modules[name].isLoad){
   99                  func &&  callBackQueue.push(func);
  100              } else  {
  101                  func &&  func();
  102               }
  103               return   this  ;
  104           }
  105       }
  106      VModule.load =  function   (name, callBackQueue) {
  107           if  (! this  .modules[name].isLoad) {
  108               var  self =  this  ;
  109               var  script =  createScript(self.modules[name].url);
  110              script.onload = script.onreadystatechange =  function   () {
  111                   if  ((! this .readyState) ||  this .readyState === "loaded" ||  this .readyState === "complete" ) {
  112                      self.modules[name].isLoad =  true  ;
  113                       //   循环调用回调队列 
 114                       for ( var  i = 0, n = callBackQueue.length;i<n;i++ ){
  115                           callBackQueue[i]();
  116                       }
  117                   }
  118               }
  119               head.appendChild(script);
  120           }
  121       }
  122  
 123      window.VM =  VModule;
  124  
 125  })();

我的测试DEMO:

 <!  DOCTYPE html  > 
 <  html  > 
 <  head  > 
     <  meta   charset  ="utf-8"  /> 
     <  title  > js模块化 </  title  > 
     <  script   type  ="text/javascript"   src  ="Module.js"  ></  script  > 
 </  head  > 
 <  body  > 
 <  p   id  ="jq"  > 测试 </  p  > 

 <  p   id  ="jq2"  > 测试 </  p  > 
 <  script   type  ="text/javascript"  >  
    VM.define(  '  a  '  , {url:  '  moduleA.js  '  , requires:[  '  b  '  ,   '  d  '  ,   '  c  '  ]})
            .define(  '  b  '  , {url:  '  moduleB.js  '  })
            .define(  '  c  '  , {url:  '  http://common.cnblogs.com/script/jquery.js?178979879891  '  })
            .define(  '  d  '  , {url:  '  moduleD.js  '  , requires:[  '  e  '  ,   '  g  '  ,   '  f  '  ]})
            .define(  '  e  '  , {url:  '  moduleE.js  '  , requires:  '  f  '  })
            .define(  '  f  '  , {url:  '  moduleF.js  '  }).define(  '  g  '  , {url:  '  moduleG.js  '  });
    VM.use(  '  a  '  ,   function   () {
        $(  '  #jq  '  ).html(  '  JQ下载成功!!  '  ).css(  '  color  '  ,   '  red  '  );
    }).use(  '  a  '  ,   function   () {
                $(  '  #jq2  '  ).html(  '  JQ下载成功!!  '  ).css(  '  color  '  ,   '  red  '  );
    }).use(  '  a  '  ,  function  (){
                $(  '  #jq2  '  ).append(  '  <em>第三次加载</em>  '  ).find(  '  em  '  ).css(  '  color  '  ,  '  blue  '  );
    }).use(  '  f  '  ,  function  (){
                console.log(  '  F加载成功!  '  );
            })

  </  script  > 
 </  body  > 
 </  html  > 

 DEMO下载地址: 点我点我点我

转载请注明出处: http://www.cnblogs.com/NNUF/

 

分类:  JS ,  实例 ,  原创

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于关于js模块加载的尝试的详细内容...

  阅读:48次