天天看點

[JavaScript] AMD和CMD概述

1. cmd 和 amd

在浏覽器中,受網絡和浏覽器渲染的制約,不能采用同步加載,隻能采用異步加載。于是 AMD 規範應運而生

2. AMD

AMD(Asynchronous Module Definition),意思就是"異步子產品定義"。它采用異步方式加載子產品,子產品的加載不影響它後面語句的運作。所有依賴這個子產品的語句,都定義在一個回調函數中,等到加載完成之後,這個回調函數才會運作

2.1 define(module,callback)定義子產品,require(module,callback)加載子產品

require(['jquery'],function($){
    $("#bg").css({background:'red'});
})           

第一個參數是一個數組,值是依賴的子產品。回調事件會在所有依賴子產品加載完畢後才會執行

2.2 預加載,在定義子產品的時候就提前加載好所有子產品

3. CMD

該規範解決的浏覽器環境下如何編寫代碼實作子產品化,該規範定義可子產品的一些遵循的特征,來支援能共用的子產品

  1. 子產品單一檔案
  2. 不應引入子產品作用域範圍内的新的***變量
  3. 懶加載

3.1 子產品定義

define(factory)定義子產品

  1. define 函數接受一個參數作為子產品工廠
  2. factory 可以是一個函數或者其他有效值
  3. 如果 factory 是一個函數,回調函數中會指定三個參數 require,exports,module
  4. 如果個 factory 不是一個函數(對象,字元串),這是子產品的接口就是目前對象,字元串
define(function(require, exports, module) {
  // do something
});           
3.2 require
  1. require 函數接收一個子產品辨別符(子產品辨別符也叫子產品 id)。
  2. require 函數傳回外部子產品的導出 API(”導出 API“是用來導出内容給外部子產品使用的)。
  3. 如果無法傳回請求的子產品, require 函數将傳回 null。
3.3 require.async
  1. require.async 接收一個子產品 Id 清單和一個可選的回調函數。
  2. 回調函數接收子產品導出作為函數參數,按照與第一個參數中的順序相同的順序列出。
  3. 如果不能傳回請求的子產品,則回調應該相應地收到 null。

3.4 exports 對象

每個子產品中都有個名叫"exports"的***變量,這是一個子產品可以在子產品執行時添加子產品 API 的對象。

3.5 module 對象

  1. module.uri:完整解析的子產品 URI(子產品 URI 的全路徑)。
  2. module.dependencies:子產品請求的辨別符(子產品 id)清單。
  3. module.exports:子產品的導出 API(”導出 API“是”用來導出什麼東西的 API“)。 它與 export 對象相同。

3.6 子產品辨別符(子產品 id)

  1. 子產品的辨別符(子產品 id)必須是字面量字元串。
  2. 子產品辨別符(子產品 id)不能有類似 .js 的檔案名擴充。
  3. 子產品辨別符(子產品 id)應該是加前/字尾的字元串,比如:foo-bar。
  4. 子產品辨別符(子產品 id)可以是相對路徑,例如: ./foo 和 ../bar.。
懶加載,在 require 時候才會加載子產品

3.7 一個簡單的示例(seajs)

color.js

define("color", function(require, exports, module) {
  var $ = require("jquery");

  var createColor = function() {
    return ["rgba(", Math.floor(Math.random() * 255), ",", Math.floor(Math.random() * 255), ",", Math.floor(Math.random() * 255), ")"];
  };

  module.exports = {
    changeBg: function() {
      $("#bg").css({
        position: "fixed",
        top: "0px",
        bottom: "0px",
        left: "0px",
        right: "0px",
        background: createColor().join("")
      });
    }
  };
});           

使用非函數的工廠包裝子產品 text.js

define({
  text: "我是初始化程式",
  text2: "我要開始執行了"
});           

init.js

define("init", function(require, exports, module) {
  var color = require("../src/color");
  var initText = require("../src/text");
  var $ = require("jquery");

  module.exports = {
    start: function() {
      console.log(initText.text + "," + initText.text2);
      $(function() {
        $("#change").click(function() {
          color.changeBg();
        });
      });
    }
  };
});           

sea.js.html

...
<body id="bg">
    <button id="change">點我我變色</button>
</body>
<script src="./lib/sea.js"></script>
<script>
  seajs.config({
    alias: {
      underscore: "underscore.js",
      init: "./src/init.js",
      color: "./src/color.js"
    }
  });

  seajs.use(["underscore", "init"], function(u, init) {
    init.start();
  });
</script>
...           

3.8 seajs 引入其他插件或庫

一般控制台報錯 xxx is not a function

一些庫不支援子產品引入或者隻支援 amd 規範的引入方式,不支援 cmd。所有需要對庫進行一些改造

//Underscore.js 1.9.1
if (typeof define === "function" && define.amd && define.amd.jQuery) {
    define("underscore", [], function() {
      return _;
    });
}


//更改如下
if (typeof define === "function" && (define.amd || define.cmd)) {
    define("underscore", [], function() {
      return _;
    });
}
//或者整個define的判斷不要了
if (typeof define === "function") {
    define("underscore", [], function() {
      return _;
    });
}           

Common Module Definition

AMD

require.js 基本使用