zoukankan      html  css  js  c++  java
  • 前端模块化(四):AMD规范

    1 概述

    AMD(Asynchronous Module Definition),也就是异步模块定义。AMD规范,制定了定义模块的规则,使得模块之间的依赖可以被异步加载。这和浏览器的异步加载模块的环境刚好适应(浏览器同步加载模块会导致性能、可用性、调试和跨域访问等问题)。

    所谓异步,就是所有的模块将被异步加载,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。这就是浏览器端模块加载器核心所在。

    AMD规范由CommonJs规范演进而来,大部分思想跟CommonJS类似,属于Modules/Async流派。但AMD规范是专注于浏览器端的,根据浏览器特点做了自己的一些定义实现。下面我们来了解一下AMD规范。

    2 define方法:定义模块

    AMD规范定义了一个自由变量或者说是全局变量 define 的函数,其作用是用来定义并暴露一个模块,函数代码如下:

    define(id?, dependencies?, factory);

    l  第一个参数,id(名字),是个字符串。它指的是定义中模块的名字,这个参数是可选的。如果没有提供该参数,模块的名字应该默认为模块加载器请求的指定脚本的名字。如果提供了该参数,模块名必须是“顶级”的和绝对的(不允许相对名字)。

    l  第二个参数,dependencies(依赖),是个定义中模块所依赖模块的数组。依赖模块必须根据模块的工厂方法优先级执行,并且执行的结果应该按照依赖数组中的位置顺序以参数的形式传入(定义中模块的)工厂方法中。

    l  第三个参数,factory(工厂方法),为模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值。

    2.1  define.amd 属性

    为了清晰的标识全局函数(为浏览器加载script必须的)遵从AMD编程接口,任何全局函数应该有一个"amd"的属性,它的值为一个对象。这样可以防止与现有的定义了define函数但不遵从AMD编程接口的代码相冲突。

    判断是否存在define.amd属性,可判断当前的文件加载是否遵循AMD规范。目前我们大部分的主流的前端库都做了AMD兼容,判断是否存在define.amd属性,然后执行对应的加载模式。例如jQuery最后几行的写法如下:

    if ( typeof define === "function" && define.amd ) {
    
        define( "jquery", [], function () { return jQuery; } );
    
    }

    2 require方法:加载模块

    require方法用于调用模块,但是不同于CommonJS,它有两个参数,与define方法类似。结构代码如下:

    require([module], callback);

    第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。如果将前面的代码改写成AMD形式,就是下面这样:

    require(['a'], function (a) {
    
        a.FuncA();
    
      });

    上面方法表示加载a模块,当这个模块加载成功后,执行一个回调函数。该回调函数就用来完成具体的任务。a.FuncA()与a模块加载不是同步的,因此在浏览器下不会发生阻塞的情况。

    AMD实例

    3.1 普通模块

    define("a", ["require", "exports", "b"], function (require, exports, b) {
    
           exports.funb = function() {
    
               return b.funb();
    
               //Or:
    
               return require("b").funb();
    
           }
    
       });

    上面例子,创建一个名为"a"的模块,使用了require,exports,和名为"b"的模块。第三个参数是回调函数,可以直接使用依赖的模块,他们按依赖声明顺序作为参数提供给回调函数。

    3.2 匿名模块

    define(["a"], function (a) {
    
           return {
    
             funb: function(){
    
               return a.funb();
    
             }
    
           };
    
       });

    上面的例子中,我们忽略了define 方法的第一个参数,这样就定义了一个匿名模块,而模块文件的文件名就是模块标识。例如,上面定义的这个模块文件放在b.js中,那么b就是它的模块名。如果其他模块想引用这个模块的话,可以在依赖项中用"b"来加载这个匿名模块。

    3.3 独立模块

    define({
    
         funA: function(a, b){
    
           return a + b;
    
         }
    
       }); 

    如果被定义的模块是一个独立模块,不需要依赖任何其他模块,可以直接用define方法生成。上面的例子中,定义了一个拥有funA方法的模块。

    3.4   非独立模块

    define(function (require, exports, module) {
    
         var a = require('a'),
    
             b = require('b');
     
    
         exports.fun = function () {
    
                 a.funA();
    
                 b.funB();
    
             };
    
       });

    上面例子中,定义的模块返回一个对象,该对象的fun方法就是外部调用的接口。这种方法与 CommonJS 方式定义有些类似。需要注意的是,回调函数必须返回一个对象,这个对象就是你定义的模块。

    下一篇我们开始介绍AMD规范的产物RequireJs加载器,进一步了解AMD规范的具体实现。

  • 相关阅读:
    课后总结
    构建之法阅读笔记01
    软件工程周总结02
    开课博客
    二维数组最大子数组和
    大二下周总结四
    大二下周总结三
    定义一个整型数组,返回该数组中子数组和的最大值
    软件工程开课
    定义一个数组返回最大子数组的值(1)
  • 原文地址:https://www.cnblogs.com/huiguo/p/7967344.html
Copyright © 2011-2022 走看看