1. 程式人生 > >AMD規範和RequireJs的簡單使用

AMD規範和RequireJs的簡單使用

AMD

  • AMD(Asynchronous Module Definition):非同步模組定義
  • 採用非同步方式載入模組,模組的載入不影響它後面語句的執行。
  • 所有依賴這個模組的語句,都定義在一個回撥函式中,等到載入完成之後,這個回撥函式才會執行。
  • 採用require()語句載入模組但是不同於CommonJS,它要求兩個引數,第一個引數[module],是一個數組,裡面的成員就是要載入的模組;第二個引數callback,則是載入成功之後的回撥函式。

RequireJs的使用

1.require.js的好處

(1)實現js檔案的非同步載入,避免網頁失去響應;
(2)管理模組之間的依賴性,便於程式碼的編寫和維護。

2.require.js的載入

  • 使用require.js的第一步,是先去官方網站下載最新版本。
  • 下載後,假定把它放在js子目錄下面,就可以載入了。
<script src="js/require.js"></script>

為避免造成網頁失去響應,解決辦法有兩個,一個是把它放在網頁底部載入,另一個是寫成下面這樣:
<script src="js/require.js" defer async="true" ></script>
async屬性表明這個檔案需要非同步載入,避免網頁失去響應。IE不支援這個屬性,只支援defer,所以把defer也寫上。

  • 下一步就要載入我們自己的程式碼了。假定我們自己的程式碼檔案是main.js,也放在js目錄下面。那麼,只需要寫成下面這樣就行了:<script src="js/require.js" data-main="js/main"></script>data-main屬性的作用是,指定網頁程式的主模組。在上例中,就是js目錄下面的main.js,這個檔案會第一個被require.js載入。由於require.js預設的檔案字尾名是js,所以可以把main.js簡寫成main。

主模組依賴於其他模組,這時就要使用AMD規範定義的的require()函式。

require
([module], callback);

例:

require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
  // some code here
});
//傳入第一個引數,要載入的模組
//傳入第二引數,回撥函式
//回撥裡面的引數列表與依賴模組名稱列表一一對應。
//載入的模組會以引數形式傳入該函式,從而在回撥函式內部就可以使用這些模組。
/*模組函式以
引數'module1'、'module2'、'module3'使用這三個
以"./module1", "./module2", "./module3"名稱指定的模組。
在這三個模組載入完畢之前,回撥函式不會被呼叫。*/

3. 模組的定義

  • 簡單的值對
define({
    attr1: 'attr1',
    attr2: 456,
});
  • 函式式定義
define(function () {
    return {
        attr1: 'attr1',
        attr2: 456,
    }
});
  • 存在依賴的函式式定義
define([
    "./module1", 
    "./module2", 
    "./module3"
], function(module1, module2, module3) {
   return {
       attr1: 'attr1',
       attr2: 456,
       addToCart: function() {
           module1.doSomething(this);
           module2.doSomething(this);
           module3.doSomething(this);
       }
   }
 }
);
  • 將模組返回值定義為一個函式
define([
    "./module1", 
    "./module2", 
], function(module1, module2) {
   return 
     function(val) {
           return val != null ? module1.a : module2.a;
     }
   }
 }
);
  • 定義一個命名模組
    (該方法使模組更不具備移植性——就是說若你將檔案移動到其他目錄下,你就得重新命名。)
define('module1',[
    "./module2", 
], function(module2) {
   //doSomething
 }
);
/*三個引數:模組名,引入模組,回撥函式

PS : 一個Javascript檔案應該只定義一個模組,這是模組名-至-檔名查詢機制的自然要求。多個模組會被優化工具組織優化,但你在使用優化工具時應將多個模組放置到一個檔案中。

4. 模組的載入

require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
  // some code here
});

主模組的依賴模組是[‘moduleA’, ‘moduleB’, ‘moduleC’]。預設情況下,require.js假定這三個模組與main.js在同一個目錄,檔名分別為moduleA.js,moduleB.js和moduleC.js,然後自動載入。
使用require.config()方法,我們可以對模組的載入行為進行自定義。
require.config()就寫在主模組(main.js)的頭部。
引數就是一個物件,這個物件的paths屬性指定各個模組的載入路徑。

  • 假設主模組依賴的三個模組和它同一個目錄下:
require.config({
 paths: {
  "moduleA": "moduleA",
  "moduleB": "moduleB",
  "moduleC": "moduleC"
  }
});
  • 假設主模組依賴的三個模組和它不在同一個目錄下:
  • 寫法一:逐一指定路徑
require.config({
 paths: {
  "moduleA": "./js/lib/moduleA",
  "moduleB": "./js/lib/moduleB",
  "moduleC": "./js/lib/moduleC"
  }
});
  • 寫法二:直接改變基目錄(baseUrl)
require.config({
  baseUrl: "js/lib",
 paths: {
  "moduleA": "moduleA",
  "moduleB": "moduleB",
  "moduleC": "moduleC"
  }
});
  • 載入網上模組
require.config({
     paths: {
          "moduleA": "https://www.xxxx.com/moduleA"
     }
});
  • 載入非規範的模組
    shim: 為那些沒有使用define()來宣告依賴關係、設定模組的”瀏覽器全域性變數注入”型指令碼做依賴和匯出配置。專門用來配置不相容的模組。具體來說,每個模組要定義
    (1)exports值(輸出的變數名),表明這個模組外部呼叫時的名稱;
    (2)deps陣列,表明該模組的依賴性。
require.config({
  shim: {
    'moduleD': {
      deps: ['moduleA', 'moduleB'],
      exports: 'moduleD'
    }
  }
});

而那些僅作為類似jQuery或Backbone的外掛存在而不匯出任何模組變數的”模組”們,shim配置可簡單設定為依賴陣列:

requirejs.config({
    shim: {
        'jquery.colorize': ['jquery'],
        'jquery.scroll': ['jquery'],
        'backbone.layoutmanager': ['backbone']
    }
});
  • 完整案例
//html 主頁面引入require.js檔案,和main.js檔案。
<script src="scripts/require.js"></script>
<script src="scripts/main.js"></script>

//main.js
require.config({
    baseUrl: "js/lib",
    paths: {
      "moduleA": "moduleA",
      "moduleB": "moduleB",
      "moduleC": "moduleC"
    },
    shim: {
        'jquery.colorize': ['jquery'],
        'jquery.scroll': ['jquery'],
        'backbone.layoutmanager': ['backbone']
    }
});
require( [
    "moduleA", 
    "moduleB", 
    "moduleC"],
  function(moduleA, moduleB, moduleC) {
      //doSomething
  }
);