AMD 規(guī)范使用總結(jié)

AMD模式

</br> define和require這兩個定義模塊、調(diào)用模塊的方法,合稱為AMD模式。它的模塊定義的方法非常清晰,不會污染全局環(huán)境,能夠清楚地顯示依賴關(guān)系。
</br>AMD模式可以用于瀏覽器環(huán)境,并且允許非同步加載模塊,也可以根據(jù)需要動態(tài)加載模塊。

define方法:定義模塊

</br>
define方法用于定義模塊,RequireJS要求每個模塊放在一個單獨的文件里。
</br>按照是否依賴其他模塊,可以分成兩種情況討論。第一種情況是定義獨立模塊,即所定義的模塊不依賴其他模塊;第二種情況是定義非獨立模塊,即所定義的模塊依賴于其他模塊。

(1)AMD實例

</br> 下面代碼定義了一個alpha模塊,并且依賴于內(nèi)置的require,exports模塊,以及外部的beta模塊??梢钥吹?,第三個參數(shù)是回調(diào)函數(shù),可以直接使用依賴的模塊,他們按依賴聲明順序作為參數(shù)提供給回調(diào)函數(shù)。
  這里的require函數(shù)讓你能夠隨時去依賴一個模塊,即取得模塊的引用,從而即使模塊沒有作為參數(shù)定義,也能夠被使用;exports是定義的alpha 模塊的實體,在其上定義的任何屬性和方法也就是alpha模塊的屬性和方法。通過exports.verb = ...就是為alpha模塊定義了一個verb方法。例子中是簡單調(diào)用了模塊beta的verb方法。

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {

  exports.verb = function() {

         return beta.verb();

      //或者:

      return require("beta").verb();
  }

});
(2)匿名模塊

</br> define 方法允許你省略第一個參數(shù),這樣就定義了一個匿名模塊,這時候模塊文件的文件名就是模塊標識。如果這個模塊文件放在a.js中,那么a就是模塊名??梢栽谝蕾図椫杏?a"來依賴于這個匿名模塊。這帶來一個好處,就是模塊是高度可重用的。你拿來一個匿名模塊,隨便放在一個位置就可以使用它,模塊名就是它的文件路徑。這也很好的符合了DRY(Don't Repeat Yourself)原則。
  下面的代碼就定義了一個依賴于alpha模塊的匿名模塊:

define(["alpha"], function (alpha) {
  return {
      verb: function(){
          return alpha.verb() + 2;
      }
  }; 
});
(3)獨立模塊

</br> 如果被定義的模塊是一個獨立模塊,不需要依賴任何其他模塊,可以直接用define方法生成。

define({
    method1: function() {},
    method2: function() {},
});

</br> 上面代碼生成了一個擁有method1、method2兩個方法的模塊。</br>另一種等價的寫法是,把對象寫成一個函數(shù),該函數(shù)的返回值就是輸出的模塊。

define(function () {
    return {
        method1: function() {},
        method2: function() {},
    };
});

</br> 后一種寫法的自由度更高一點,可以在函數(shù)體內(nèi)寫一些模塊初始化代碼。</br>

值得指出的是,define定義的模塊可以返回任何值,不限于對象。

(4)非獨立模塊

</br> 如果被定義的模塊需要依賴其他模塊,則define方法必須采用下面的格式。

define(['module1', 'module2'], function(m1, m2) {
   ...
});

</br> define方法的第一個參數(shù)是一個數(shù)組,它的成員是當前模塊所依賴的模塊。比如,['module1', 'module2']表示我們定義的這個新模塊依賴于module1模塊和module2模塊,只有先加載這兩個模塊,新模塊才能正常運行。一般情況下,module1模塊和module2模塊指的是,當前目錄下的module1.js文件和module2.js文件,等同于寫成['./module1', './module2']。</br>
define方法的第二個參數(shù)是一個函數(shù),當前面數(shù)組的所有成員加載成功后,它將被調(diào)用。它的參數(shù)與數(shù)組的成員一一對應(yīng),比如function(m1, m2)就表示,這個函數(shù)的第一個參數(shù)m1對應(yīng)module1模塊,第二個參數(shù)m2對應(yīng)module2模塊。這個函數(shù)必須返回一個對象,供其他模塊調(diào)用。

define(['module1', 'module2'], function(m1, m2) {

    return {
        method: function() {
            m1.methodA();
            m2.methodB();
        }
    };

});

</br>上面代碼表示新模塊返回一個對象,該對象的method方法就是外部調(diào)用的接口,menthod方法內(nèi)部調(diào)用了m1模塊的methodA方法和m2模塊的methodB方法。</br>

需要注意的是,回調(diào)函數(shù)必須返回一個對象,這個對象就是你定義的模塊。</br>
如果依賴的模塊很多,參數(shù)與模塊一一對應(yīng)的寫法非常麻煩。

define(
    [ 'dep1', 'dep2', 'dep3', 'dep4', 'dep5', 'dep6', 'dep7', 'dep8'],
    function(dep1,   dep2,   dep3,   dep4,   dep5,   dep6,   dep7,   dep8){
        ...
    }
);

</br> 為了避免像上面代碼那樣繁瑣的寫法,RequireJS提供一種更簡單的寫法。

define(
    function (require) {
        var dep1 = require('dep1'),
            dep2 = require('dep2'),
            dep3 = require('dep3'),
            dep4 = require('dep4'),
            dep5 = require('dep5'),
            dep6 = require('dep6'),
            dep7 = require('dep7'),
            dep8 = require('dep8');
    }
});

</br>下面是一個define實際運用的例子。

define(['math', 'graph'], 
    function ( math, graph ) {
        return {
            plot: function(x, y){
                return graph.drawPie(math.randomGrid(x,y));
            }
        }
    };
);

</br>上面代碼定義的模塊依賴math和graph兩個庫,然后返回一個具有plot接口的對象。</br>
另一個實際的例子是,通過判斷瀏覽器是否為IE,而選擇加載zepto或jQuery。

define(('__proto__' in {} ? ['zepto'] : ['jquery']), function($) {
    return $;
});

</br>上面代碼定義了一個中間模塊,該模塊先判斷瀏覽器是否支持proto屬性(除了IE,其他瀏覽器都支持),如果返回true,就加載zepto庫,否則加載jQuery庫。

require方法:調(diào)用模塊

</br>require方法用于調(diào)用模塊。它的參數(shù)與define方法類似。

require(['foo', 'bar'], function ( foo, bar ) {
        foo.doSomething();
});

</br>上面方法表示加載foo和bar兩個模塊,當這兩個模塊都加載成功后,執(zhí)行一個回調(diào)函數(shù)。該回調(diào)函數(shù)就用來完成具體的任務(wù)。</br>
require方法的第一個參數(shù),是一個表示依賴關(guān)系的數(shù)組。這個數(shù)組可以寫得很靈活,請看下面的例子。

require( [ window.JSON ? undefined : 'util/json2' ], function ( JSON ) {
  JSON = JSON || window.JSON;
  console.log( JSON.parse( '{ "JSON" : "HERE" }' ) );
});

</br> 上面代碼加載JSON模塊時,首先判斷瀏覽器是否原生支持JSON對象。如果是的,則將undefined傳入回調(diào)函數(shù),否則加載util目錄下的json2模塊。</br>
require方法也可以用在define方法內(nèi)部。

define(function (require) {
   var otherModule = require('otherModule');
});

</br>下面的例子顯示了如何動態(tài)加載模塊。

define(function ( require ) {
    var isReady = false, foobar;
 
    require(['foo', 'bar'], function (foo, bar) {
        isReady = true;
        foobar = foo() + bar();
    });
 
    return {
        isReady: isReady,
        foobar: foobar
    };
});

</br>上面代碼所定義的模塊,內(nèi)部加載了foo和bar兩個模塊,在沒有加載完成前,isReady屬性值為false,加載完成后就變成了true。因此,可以根據(jù)isReady屬性的值,決定下一步的動作。</br>
下面的例子是模塊的輸出結(jié)果是一個promise對象。

define(['lib/Deferred'], function( Deferred ){
    var defer = new Deferred(); 
    require(['lib/templates/?index.html','lib/data/?stats'],
        function( template, data ){
            defer.resolve({ template: template, data:data });
        }
    );
    return defer.promise();
});

</br>上面代碼的define方法返回一個promise對象,可以在該對象的then方法,指定下一步的動作。</br>
如果服務(wù)器端采用JSONP模式,則可以直接在require中調(diào)用,方法是指定JSONP的callback參數(shù)為define。

require( [ 
    "http://someapi.com/foo?callback=define"
], function (data) {
    console.log(data);
});

</br> require方法允許添加第三個參數(shù),即錯誤處理的回調(diào)函數(shù)。

require(
    [ "backbone" ], 
    function ( Backbone ) {
        return Backbone.View.extend({ /* ... */ });
    }, 
    function (err) {
        // ...
    }
);

</br>require方法的第三個參數(shù),即處理錯誤的回調(diào)函數(shù),接受一個error對象作為參數(shù)。</br>
require對象還允許指定一個全局性的Error事件的監(jiān)聽函數(shù)。所有沒有被上面的方法捕獲的錯誤,都會被觸發(fā)這個監(jiān)聽函數(shù)。

requirejs.onError = function (err) {
    // ...
};

實際應(yīng)用

//定義M模塊,本申明一個全局變量
define('M',[],function(){
    window.M={};
    return M;
})
//定義模塊a 依賴模塊 M,b,c
define('a',['M','b','c'],function(M){
    alert(M.ob);
    alert(M.oc);
})
//定義b模塊
define('b',[],function(){
    M.ob = 2;
    return M;
})
//定義c模塊
define('c',[],function(){
    M.oc = 3;
    return M;
})
//引入a模塊
require(['a'],function(a){
    
})

此例子里邊需要注意:

</br>M模塊的作用是定義一個全局的變量;</br>

a模塊依賴了其他模塊,但是function 參數(shù)缺只有M一個參數(shù),但是也可以用使用b,c兩個模塊里邊的變量,這是因為 M 模塊里邊的全局變量。可以看得出 b,c模塊里邊的變量在申明的時候就是掛在全局變量下的。所以a模塊依賴了b,c模塊缺沒有使用參數(shù)接口,也可以用的原因。</br>

反之,變量沒有掛在全局變量下,引用了模塊,沒有用參數(shù)接受,這樣是不可以使用其他模塊下邊的變量和方法的,因為很簡單是作用局的問題。</br>

還有就是b,c模塊沒有引用M模塊缺使用了,M模塊下邊的變量,也是因為此變量是全局變量。如果是局部變量,那就要依賴于M模塊才可以使用了。</br>

假如說,反正b,c兩個模塊也不用參加接收,都掛在了全局變量下邊,是不是不引也可以,直接引一個M模塊好了。這肯定是不行的,會彈出 undefined

</br>


http://www.360doc.com/content/16/0415/14/32473389_550841188.shtml

http://www.cnblogs.com/happyPawpaw/archive/2012/05/31/2528864.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1 個人理解;有錯希望大家指出;稍后更新拖拽上傳文件; 2、commonJS commonjs的目標是制定一個js...
    吳高亮閱讀 1,627評論 0 2
  • 為什么要使用模塊化? 最主要的目的:解決命名沖突依賴管理 其他價值提高代碼可讀性代碼解耦,提高復用性 CMD、AM...
    Eazer閱讀 766評論 3 1
  • 在JavaScript模塊一文中介紹了如何組織代碼實現(xiàn)模塊化。模塊化能隱藏私有的屬性和方法,只暴露出公共接口。這樣...
    張歆琳閱讀 11,032評論 1 26
  • 我們要經(jīng)過多少次尋找 才能得到—— 窗外的陽光耀眼 屋內(nèi)舞曲依然火熱 一復一日 磨卻了夢想 被時間遺忘 想要抓在手...
    陽光下泡腳丫閱讀 190評論 2 2
  • 剛剛讀完《渴望生活-梵高傳》,佩服歐文-斯通的寫作手法,將一個人描繪的那么真實,從他二十幾歲開始步入社會,...
    有夢想ed咸魚閱讀 322評論 0 2

友情鏈接更多精彩內(nèi)容