前端模組化(CommonJs,AMD和CMD)

來源:互聯網
上載者:User

標籤:迴文   它的   完成   jquery   頁面   type   types   comment   sea   

前端模組規範有三種:CommonJs,AMD和CMD。

CommonJs用在伺服器端,AMD和CMD用在瀏覽器環境
AMD 是 RequireJS 在推廣過程中對模組定義的正常化產出。
CMD 是 SeaJS 在推廣過程中對模組定義的正常化產出。
AMD:提前執行(非同步載入:依賴先執行)+順延強制
CMD:順延強制(運行到需載入,根據順序執行)

模組
  • 函數寫法
      function f1(){    //...  }  function f2(){    //...  }
    模組就是實現特定功能的檔案,把幾個函數放在一個檔案裡就構成了一個模組。需要的時候載入這個檔案,調用其中的函數即可。
    但這樣做會汙染全域變數,無法保證不與其他模組發生變數名衝突,而且模組成員之間沒什麼關係。
  • 對象寫法
        var module = {    star : 0,    f1 : function (){      //...    },    f2 : function (){      //...    }  };    module.f1();    module.star = 1;
    模組寫成一個對象,模組成員都封裝在對象裡,通過調用對象屬性,訪問使用模組成員。但同時也暴露了模組成員,外部可以修改模組內部狀態。
  • 立即執行函數
        var module = (function(){    var star = 0;    var f1 = function (){      console.log(‘ok‘);    };    var f2 = function (){      //...    };       return {          f1:f1,          f2:f2       };  })();    module.f1();  //ok    console.log(module.star)  //undefined
    外部無法訪問內部私人變數
CommonJs

CommonJS是伺服器端模組的規範,由Node推廣使用。由於服務端編程的複雜性,如果沒有模組很難與作業系統及其他應用程式互動。使用方法如下:

math.jsexports.add = function() {    var sum = 0, i = 0, args = arguments, l = args.length;    while (i < l) {      sum += args[i++];    }    return sum;};increment.jsvar add = require(‘math‘).add;exports.increment = function(val) {    return add(val, 1);};index.jsvar increment = require(‘increment‘).increment;var a = increment(1); //2

根據CommonJS規範:

  • 一個單獨的檔案就是一個模組。每一個模組都是一個單獨的範圍,也就是說,在該模組內部定義的變數,無法被其他模組讀取,除非定義為global對象的屬性。
  • 輸出模組變數的最好方法是使用module.exports對象。

  • 載入模組使用require方法,該方法讀取一個檔案並執行,返迴文件內部的module.exports對象

仔細看上面的代碼,您會注意到 require 是同步的。模組系統需要同步讀模數塊檔案內容,並編譯執行以得到模組介面。
然而, 這在瀏覽器端問題多多。

瀏覽器端,載入 JavaScript 最佳、最容易的方式是在 document 中插入<script>標籤。但指令碼標籤天生非同步,傳統 CommonJS 模組在瀏覽器環境中無法正常載入。

解決思路之一是,開發一個伺服器端組件,對模組代碼作靜態分析,將模組與它的依賴列表一起返回給瀏覽器端。 這很好使,但需要伺服器安裝額外的組件,並因此要調整一系列底層架構。

另一種解決思路是,用一套標準模板來封裝模組定義:

define(function(require, exports, module) {  // The module code goes here});

這套模板代碼為模組載入器提供了機會,使其能在模組代碼執行之前,對模組代碼進行靜態分析,並動態產生依賴列表。

math.jsdefine(function(require, exports, module) {  exports.add = function() {    var sum = 0, i = 0, args = arguments, l = args.length;    while (i < l) {      sum += args[i++];    }    return sum;  };});increment.jsdefine(function(require, exports, module) {  var add = require(‘math‘).add;  exports.increment = function(val) {    return add(val, 1);  };});index.jsdefine(function(require, exports, module) {  var inc = require(‘increment‘).increment;  inc(1); // 2});
AMD

AMD是"Asynchronous Module Definition"的縮寫,意思就是"非同步模組定義"。由於不是JavaScript原生支援,使用AMD規範進行頁面開發需要用到對應的庫函數,也就是大名鼎鼎RequireJS,實際上AMD 是 RequireJS 在推廣過程中對模組定義的正常化的產出

它採用非同步方式載入模組,模組的載入不影響它後面語句的運行。所有依賴這個模組的語句,都定義在一個回呼函數中,等到載入完成之後,這個回呼函數才會運行。

RequireJS主要解決兩個問題

  • 多個js檔案可能有依賴關係,被依賴的檔案需要早於依賴它的檔案載入到瀏覽器
  • js載入的時候瀏覽器會停止頁面渲染,負載檔案越多,頁面失去回應時間越長

RequireJs也採用require()語句載入模組,但是不同於CommonJS,它要求兩個參數:

第一個參數[module],是一個數組,裡面的成員就是要載入的模組;第二個參數callback,則是載入成功之後的回呼函數。math.add()與math模組載入不是同步的,瀏覽器不會發生假死。

require([module], callback);require([increment‘], function (increment) {    increment.add(1);});
define()函數

RequireJS定義了一個函數 define,它是全域變數,用來定義模組:
define(id?, dependencies?, factory);
參數說明:

  • id:指定義中模組的名字,可選;如果沒有提供該參數,模組的名字應該預設為模組載入器請求的指定指令碼的名字。如果提供了該參數,模組名必須是“頂級”的和絕對的(不允許相對名字)。

  • 依賴dependencies:是一個當前模組依賴的,已被模組定義的模組標識的數組字面量。
    依賴參數是可選的,如果忽略此參數,它應該預設為["require", "exports", "module"]。然而,如果Factory 方法的長度屬性小於3,載入器會選擇以函數的長度屬性指定的參數個數調用Factory 方法。

  • Factory 方法factory,模組初始化要執行的函數或對象。如果為函數,它應該只被執行一次。如果是對象,此對象應該為模組的輸出值。

來舉個??看看:

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {       exports.verb = function() {           return beta.verb();           //Or:           return require("beta").verb();       }   });
RequireJs使用例子

require.config是用來定義別名的,在paths屬性下配置別名。然後通過requirejs(參數一,參數二);參數一是數組,傳入我們需要引用的模組名,第二個參數是個回呼函數,回呼函數傳入一個變數,代替剛才所引入的模組。

main.js//別名配置requirejs.config({    paths: {        jquery: ‘jquery.min‘ //可以省略.js    }});//引入模組,用變數$表示jquery模組requirejs([‘jquery‘], function ($) {    $(‘body‘).css(‘background-color‘,‘red‘);});

引入模組也可以唯寫require()requirejs通過define()定義模組,定義的參數上同。在此模組內的方法和變數外部是無法訪問的,只有通過return返回才行.

math.jsdefine(‘math‘,[‘jquery‘], function ($) {//引入jQuery模組    return {        add: function(x,y){            return x + y;        }    };});

將該模組命名為math.js儲存。

require([‘jquery‘,‘math‘], function ($,math) {    console.log(math.add(10,100));//110});

main.js引入模組方法

CMD

CMD 即Common Module Definition通用模組定義,CMD規範是國內發展出來的,就像AMD有個requireJS,CMD有個瀏覽器的實現SeaJSSeaJS要解決的問題和requireJS一樣,只不過在模組定義方式和模組載入(可以說運行、解析)時機上有所不同。

在 CMD 規範中,一個模組就是一個檔案。代碼的書寫格式如下:

define(function(require, exports, module) {  // 模組代碼});

require是可以把其他模組匯入進來的一個參數;而exports是可以把模組內的一些屬性和方法匯出的;module 是一個對象,上面儲存了與當前模組相關聯的一些屬性和方法。

AMD是依賴關係前置,在定義模組的時候就要聲明其依賴的模組;
CMD是按需載入依賴就近,只有在用到某個模組的時候再去require:

// CMDdefine(function(require, exports, module) {  var a = require(‘./a‘)  a.doSomething()  // 此處略去 100 行  var b = require(‘./b‘) // 依賴可以就近書寫  b.doSomething()  // ... })// AMD 預設推薦的是define([‘./a‘, ‘./b‘], function(a, b) { // 依賴必須一開始就寫好  a.doSomething()  // 此處略去 100 行  b.doSomething()  ...})
seajs使用例子
// 定義模組  myModule.jsdefine(function(require, exports, module) {  var $ = require(‘jquery.js‘)  $(‘div‘).addClass(‘active‘);  exports.data = 1;});// 載入模組seajs.use([‘myModule.js‘], function(my){    var star= my.data;    console.log(star);  //1});
參考

這篇《前端模組化:CommonJs,AMD和CDM》主要是個人對以下文章的總結,感謝這些老司機們的分享。
前端模組化
詳解JavaScript模組化開發
Javascript模組化編程
從 CommonJS 到 Sea.js

前端模組化(CommonJs,AMD和CMD)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.