AMD, Asynchronous Module Definition,即異步模塊加載機(jī)制,它采用異步方式加載模塊,模塊的加載不影響它后面語句的運(yùn)行。所有依賴這個模塊的語句都定義在一個回調(diào)函數(shù)中,等到依賴加載完成之后,這個回調(diào)函數(shù)才會運(yùn)行。
AMD 的誕生,就是為了解決這兩個問題:
實現(xiàn) JavaScript 文件的異步加載,避免網(wǎng)頁失去響應(yīng)
管理模塊之間的依賴性,便于代碼的編寫和維護(hù)
AMD標(biāo)準(zhǔn)中,定義了下面兩個API:
1.require([module], callback)
2. define(id, [depends], callback)
// 模塊定義
define(id?: String, dependencies?: String[], factory: Function|Object);
id 是模塊的名字,它是可選的參數(shù)。
dependencies 指定了所要依賴的模塊列表,它是一個數(shù)組,也是可選的參數(shù)。每個依賴的模塊的輸出都將作為參數(shù)一次傳入 factory 中。如果沒有指定 dependencies,那么它的默認(rèn)值是 ["require", "exports", "module"]。
factory 是最后一個參數(shù),它包裹了模塊的具體實現(xiàn),它是一個函數(shù)或者對象。如果是函數(shù),那么它的返回值就是模塊的輸出接口或值,如果是對象,此對象應(yīng)該為模塊的輸出值。
這里主要是根據(jù)模塊的 Url,創(chuàng)建了一個異步的 Script 標(biāo)簽,并將模塊 id 名稱添加到的標(biāo)簽的 data-requiremodule 上,再將這個 Script 標(biāo)簽添加到了 html 頁面中。同時為 Script 標(biāo)簽的 load 事件添加了處理函數(shù),當(dāng)該模塊文件被加載完畢的時候,就會觸context.onScriptLoad。
但是,在使用require.js的時候,我們必須要提前加載所有的依賴,然后才可以使用,而不是需要使用時再加載。
優(yōu)點(diǎn):
適合在瀏覽器環(huán)境中異步加載模塊??梢圆⑿屑虞d多個模塊。
缺點(diǎn):
提高了開發(fā)成本,并且不能按需加載,而是必須提前加載所有的依賴。
//myModule1.js
define(function() {
var m1 = {};
m1.say = function() {
console.log('Hi myModule1!');
}
return m1;
});
//myModule2.js
define(['myModule3'], function(m3) {
var m2 = {};
m2.say = function() {
m3.say();
console.log('Hi myModule2!');
}
return m2;
});
//myModule3.js
define(function() {
var m3 = {};
m3.say = function() {
console.log('Hi myModule3!');
}
return m3;
});
//HTML
console.log("before require");
require(['myModule1','myModule2'], function(m1, m2){
m1.say();
m2.say();
});
console.log("after require");
//before require
//after require
//Hi myModule1!
//Hi myModule3!
//Hi myModule2!
HTML中先執(zhí)行console.log(“before require”);,打印出第一條。
然后執(zhí)行require,因為require.js是AMD異步加載,所以執(zhí)行require后的console.log(“after require”);語句,打印出第二條。
執(zhí)行require依次加載模塊。先加載myModule1。發(fā)現(xiàn)myModule1的define里無[depends]參數(shù),不依賴其他模塊。因此運(yùn)行define里的factory方法獲得myModule1的實例對象m1。
再加載myModule2。發(fā)現(xiàn)myModule2依賴myModule3,因此加載myModule3。myModule3無[depends]參數(shù),不依賴其他模塊。因此運(yùn)行factory獲得myModule3的實例對象m3。
加載完myModule3后,運(yùn)行myModule2的factory獲得myModule2的實例對象m2。
myModule2也加載完畢后,require的所有模塊均加載完畢,運(yùn)行回調(diào)函數(shù)。前面獲得的實例對象m1和m2作為參數(shù)傳給回調(diào)函數(shù)。
運(yùn)行m1.say();打印出第三條
運(yùn)行m2.say();,根據(jù)方法定義,先運(yùn)行m3.say();打印出第四條,再運(yùn)行console.log(‘Hi myModule2!’);打印出第五條。