[JavaScript] AMD/CMD/UMD概述


1. cmd 和 amd

在瀏覽器中,受網絡和瀏覽器渲染的制約,不能采用同步加載,只能采用異步加載。於是 AMD 規范應運而生

2. AMD

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

2.1 define 函數定義模塊

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

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("")
        });
    })

});

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

2.3 預加載,在定義模塊的時候就提前加載好所有模塊

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)

這是 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 {};
}));


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM