在可擴充JavaScript的世界裡,如果我們說一個應用程式是模組化(modular)的,那麼通常意味著它是由一系列儲存於模組中的高度解耦,不同的功能片段組成。在可能的情況下,通過一處依賴性,松耦合可以使應用程式的可維護性更加簡單。 如果有效地實現了這點,就很容易地瞭解一部分如何影響另一個部分。
非同步模組定義(AMD)的整體目標是提供模組化的JavaScript解決方案,以便開發人員使用。誕生於使用XHR+eval的Dojo開發經驗,這種格式的支援者希望能夠避免未來的任何解決方案受到過去解決方案缺點的影響。 AMD模組格式本身就是對定義模組的建議,其模組和依賴都將可以進行非同步載入。
AMD最開始是CommonJS重模組格式的草案規範,但由於沒有達到廣泛的一致,這種格式的進一步發展就轉移到了amdjs社區(https://github.com/amdjs)。
一、模組入門
關於AMD有兩個關鍵概念是值得我們注意的,他們是用於模組定義的define方法和用於處理依賴載入的require方法。試用一下方法,define用於定義已命名或未命名模組:
define( module_id /*可選*/, [dependencies] /*可選*/, definition function /*function for instantiating the module or object執行個體化模組或對象的函數*/)
module_id是一個選擇性參數,它通常只在非AMD 串連工具被使用時才需要。當遺漏這個參數時,我們稱這個模組未匿名的(anonymous)。
當使用這個匿名模組時,模組身份的概念是DRY,以便更容易避免檔案名稱和代碼重複。因為代碼變得更輕便了,不需要修改代碼本身或改變其模組ID,就可以將它很容易地移動到其他位置。
Developers可以僅僅通過使用AMD最佳化器在多個環境中運行相同的代碼,AMD最佳化器在CommonJS環境(譬如r.js https://github.com/jrburke/r.js/)下工作。
define ("myModule", //定義一個module ['foo', 'bar'], function (foo, bar) { //模組定義函數,依賴foo bar 作為參數映射到函數上
//這裡建立你的模組 var myModule = { dostuff: function () { console.log('yay, stuff'); } }; return myModule; } );
//另外一種定義方式 define('myModule', ['math', 'graph'], function (math, graph) { return { plot: function(x, y) { return graph.drawPie(math.randomGrid(x, y)); } } });
require通常用於載入頂級JavaScript檔案或模組的代碼。
//foo bar是兩個外部模組,兩個模組載入以後輸出作為回呼函數的參數傳入require(['foo', 'bar'], function (foo, bar) { // foo.doSomething();})
動態載入依賴
define(function (require) { var isReady = false, foobar; require(['foo', 'bar'], function (foo, bar) { isReady = true; foobar = foo() + bar(); }); return { isReady: isReady, foobar: foobar }})
瞭解 AMD: 外掛程式
//使用AMD可以載入任意格式的內容//這種方式可以用於模板依賴,以便在頁面載入的時候進行做換膚方面的工作define(['./templates', 'text!./template.md', 'css!./template.css'], function (templates, template) { console.log(templates);});
雖然在上面的樣本重包含css!用於載入css依賴,但這種方法會有一些警告。黨css完全被載入時,它不一定完全生效。取決於如何處理建立過程,它也可能使用css作為一個依賴檔案而被包含在最佳化的檔案中,因此,在將css作為載入依賴使用的情況下,一定要謹慎。
該樣本可以簡單看作是requirejs(['app/myModule'], function () {}),表明載入器的頂級全域對象被使用。這裡示範了如何使用不同的AMD載入器載入頂級模組nahor,通過使用define()函數,如果塔接受了一個本地模組參數,那麼所有require([])的樣本都適用於curl.js 和 RequireJS這兩種類型的載入器。