[JavaScript] AMD/CMD/UMD概述

1. cmd 和 amd

在瀏覽器中,受網絡和瀏覽器渲染的制約,不能採用同步加載,只能採用異步加載。因而 AMD 規範應運而生javascript

2. AMD

AMD(Asynchronous Module Definition),意思就是"異步模塊定義"。它採用異步方式加載模塊,制定了定義模塊的規則,這樣模塊和模塊的依賴能夠被異步加載,不影響它後面語句的運行。全部依賴這個模塊的語句,都定義在一個回調函數中,等到加載完成以後,這個回調函數纔會運行。這和瀏覽器的異步加載模塊的環境恰好適應(瀏覽器同步加載模塊會致使性能、可用性、調試和跨域訪問等問題)css

2.1 define 函數定義模塊

本規範只定義了一個函數 "define",它是全局變量 define(id?, dependencies?, factory),參數分別是模塊名,依賴,工廠方法html

2.2 require(module,callback)加載模塊

  • 引入 require.js
<script type=」text/javascript」 defer async=」true」 src=」./require.js」></script>
<script type=」text/javascript」 defer async=」true」 src=」js/init.js」></script>
  • init.js
//require.config 主要是用來對要加載文件的目錄進行自定義
require.config({
  baseUrl: 'js',
  paths: {
    "jquery": "../lib/jquery",
    "undersocre": "../lib/underscore",
  }
})

require(['jquery', 'underscore'], function ($, _) {
    $(window).resize(function () {

        var color = ["rgba(", Math.floor(Math.random() * 255), ",", Math.floor(Math.random() * 255), ",", Math.floor(Math.random() * 255), ")"];

        $(".background").css({
            position: "fixed",
            top: "0px",
            bottom: "0px",
            left: "0px",
            right: "0px",
            background: color.join("")
        });
    })

});

第一個參數是一個數組,值是依賴的模塊。回調事件會在全部依賴模塊加載完畢後纔會執行java

2.3 預加載,在定義模塊的時候就提早加載好全部模塊

3. CMD

該規範解決的瀏覽器環境下如何編寫代碼實現模塊化,該規範定義可模塊的一些遵循的特徵,來支持能共用的模塊jquery

  1. 模塊單一文件
  2. 不該引入模塊做用域範圍內的新的自由變量
  3. 懶加載

3.1 模塊定義

define(factory)定義模塊git

  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 的對象。github

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 時候纔會加載模塊api

3.7 一個簡單的示例(seajs)

這是 seajs 對象上綁定的屬性和方法跨域

seajs01

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>
...

目錄結構
seajs02

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 _;
});
}

UMD

是一種思想,就是一種兼容 commonjs,AMD,CMD 的兼容寫法,define.amd / define.cmd / module 等判斷當前支持什麼方式,都不行就掛載到 window 全局對象上面去

(function (root, factory) {
    if (typeof define === 'function' && (define.amd || define.cmd)) {
        //AMD,CMD
        define(['b'], function(b){
          return (root.returnExportsGlobal = factory(b))
        });
    } else if (typeof module === 'object' && module.exports) {
        //Node, CommonJS之類的
        module.exports = factory(require('b'));
    } else {
        //公開暴露給全局對象
        root.returnExports = factory(root.b);
    }
}(this, function (b) {
  return {};
}));
相關文章
相關標籤/搜索