zoukankan      html  css  js  c++  java
  • 我的模块加载系统 v17

    本版本的重要更新是完全实现AMD规范。整个框架根据此新加载器重写,因此可以方便调用老外用AMD规范写好的JS库了.

    • 日志打印可以通过设置$.core.level排除某些不重要的日志打印。
    • 添加config方法来设置框架的一些重要信息或对模块进行别名。
    • 在VS系列实现智能提示。

    有关本模块加载系统的使用,可以到这里详看教程.新加载器是同时支持AMD与玉伯搞的seajs的CMD.如果你在模块定义中的回调带有"require","exports","modules"中的任两个,加载器就视为CMD.不过无视是AMD与CMD,函数里面require, modules, exports都是可用的,完全可以像node.js这样加载模块.

    有关require方法的模块标识,可以见这里

    有关为什么要用AMD来管理我们的脚本,我想做过一些大项目的人应该心中有数,这不是一个合并JS所能取替的,详见此文


    下面揭载我的加载器的运作机理,姑且从一个没有依赖的模块着手,比如

                $.require("$lang_fix", function(){
                    console.log("xxxxxxxxxxxxxx")
                })
    

    不用说,进入$.require(希望大家看这东西时,打开源码对照着看。)

     String(list).replace( $.rword, function(el){
    
      })
    
    el  = "$lang_fix"
    

    进入Module._resolveFilename

    
    url = $.core.base + el + ".js"
    

    初次加载,肯定没有在modules中注册, modules[url]为undefined

    于是进入 loadJS( url, id );

    • 创建一个iframe,
    • 在第一个script节点 用nick, Ns, nick分别保存url, $, innerDefine
    • 在第二个script节点 用url去加载目标节点

    第二个节点视情况不同分别绑定onreadystatechange, onload, onerror

    值得注意的是我们在注册模块时state还是为undefined,它会在innerDefine中修改state。

    然后我们通过iframe中的script加载模块,而模块一般是这样的格式
    define("lang_fix", function( ){
      //==========略============
    })
    

    这里的define实质上是innerDefine

    innerDefine里面做了几个很重要的事情(我们现在只需看第一,第二)

    1. 第一个事情把lang_fix这第一个参数换掉,换成nick, nick就是加载它的那个script的src。
    2. 第二个事情是将它对应的模块的状态改为1,也是modules[url].state = 1。
    3. 第三个事情是$, exports, require, module等对象强塞进模块工厂
    4. 第四个事情是转交真正的$.define去处理

    在第二事情中,我们将模块的状态修改了,于是节点执行onreadystatechange/onload时

    if(/loaded|complete|undefined/i.test(this.readyState) }{
        Ns._checkDeps();
         Ns._checkFail(self.document, nick);
    }
    

    Ns._checkFail发挥效力

    _checkFail : function(  doc, id, error ){
        doc && (doc.ok = 1);
        if( error || !modules[ id ].state ){
             this.log("Failed to load [[ "+id+" ]]"+modules[ id ].state);
        }
    },
    

    如果是死链,那无法调用define函数,也就无法调用innerDefine,状态为undefine

    !modules[ id ].state == true,于是打印错误日志,当然以后我们讨论一下,是不是该throw

    如果在旧式opera,它是会无法进入onreadystatechange, onload, onerror任一回调

    在_checkFail中,我们会修复doc.ok = 1,那么在iframe中onload中我们检测doc.ok不等于1时,

    就在_checkFail传入第三个参数true,让它打印错误日志

    如果在FF,chrome, IE9,它们就会进入onerror回调,那里的调用代码中

    
    Ns._checkFail(self.document, nick, true)
    

    因此也顺利检测到死链。

    反正只要加载失败,我们就立即把对应iframe移出DOM树!

    好了,如果成功加载,我们就通过innerDefine到达$.define,并也把对应iframe移出DOM树

    $.define干了如下几个事情

    1. 第一个事情,检测第二个参数是否为布尔,是说明其是补丁模块,如果布尔值为true,说明这个补丁模块对这个浏览器是没有用的,直接return,不执行它的模块工厂了。如果为false,比如IE6,补丁模块对它总是有用,先去掉此参数,继续往下执行。
    2. 第二个事情,检测参数个数,如果只有两个,说明只有模块名与模块的回调(亦有可能不是回调),那么我们插入一个空数组作为依赖列表
    3. 第三个就是检测第三个参数是否为函数,不是函数,比如说是个对象,我们要将它塞入一个函数

    比如

    
    define({
      aaa:2
    })
    

    经上面几次转换,依次变为

    
    define("http://xxxxxxx/aa.js",{
      aaa:2
    });
    //---->
    define("http://xxxxxxx/aa.js" ,[],{
      aaa:2
    });
    
    //---->
    define("http://xxxxxxx/aa.js" ,[], function(){
     return {
        aaa:2
      }
    });
    
    //---->
    $.require([], function(){
     return {
        aaa:2
      }
    }), "http://xxxxxxx/aa.js")
    

    最后我们将参数的顺序重排一下,再次调用$.require

     //0,1,2 --> 1,2,0
     this.require( args[1], args[2], parent );
    

    由于lang_fix是没有依赖的,因此dn === cn 相当于 0 == 0,执行install( id, args, factory );

    install简而言之是将模块工厂执行,将state改为2。

    我们还需要注意一下,我们每次调用$.require或加载一个脚本时都执行_checkDeps方法。

    当lang_fix的状态改为2后

    
    
     $.require("$lang_fix", function(){
          console.log("xxxxxxxxxxxxxx")
     })
    

    这个回调也将执行!

    控制台打印xxxxxxxxxxxxxxxx

    源码位于这里

  • 相关阅读:
    可爱的中国电信 请问我们的电脑还属于我们自己吗?
    了解客户的需求,写出的代码或许才是最优秀的............
    DELPHI DATASNAP 入门操作(3)简单的主从表的简单更新【含简单事务处理】
    用数组公式获取字符在字符串中最后出现的位置
    在ehlib的DBGridEh控件中使用过滤功能(可以不用 MemTableEh 控件 适用ehlib 5.2 ehlib 5.3)
    格式化json返回的时间
    ExtJs中使用Ajax赋值给全局变量异常解决方案
    java compiler level does not match the version of the installed java project facet (转)
    收集的资料(六)ASP.NET编程中的十大技巧
    收集的资料共享出来(五)Asp.Net 权限解决办法
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/2662477.html
Copyright © 2011-2022 走看看