2015年10月24日 星期六

dojo AMD

dojo AMD

簡介

將應用程式模組化,這個觀念在軟體業界己經行之有年。程式經過詳細規劃並模組化後,比較容易撰寫、管理及維護。在 dojo 中,一個模組 (module) 在系統中就是一個檔案,每當使用 require() 要求載入一個模組時,載入器 (loader) 便會在檔案系統中尋找符合名稱的模組檔案,將其載入到 Javascript 的執行環境中,程式便會獲得一個參考值;並透過這個參考值讀取模組中的屬性值,或呼叫模組中的函式。只要知道在 dojo 中如何建立一個類別 (Class)之後,建立一個模組並非難事。

建立一個模組時,最重要的就是 define() 函式。其語法如下:

define(
  moduleId,
  // (optional; string)
  // an explicit module identifier naming the module being defined      
  dependencies,  
  // (optional; array of strings) 
  // list of module identifiers to load before calling factory
  factory 
  // (function or value) 
  // the value of the module, or a function that returns the value of the  
  // module
)
    moduleId
    指定模組的名稱,這個參數是選項,一般都不賦予值;從缺時,載入器 (loader) 便使用檔案名稱做為模組的名稱。模組若是用在定義一個類別時,檔案名稱開頭的第一個字母都會大寫,以符合物件導向程式語言的命名慣例,若是傳回一個物件,則檔案名稱的第一個字母則保持小寫。
    dependencies
    也是選項,不賦予值時,表示該模組完全獨立存在,與其它模組不相關。若模組的建立需依賴其它模組,也就是會使用到其它的模組時,要將所有相依的模組名稱放在陣列裡傳入。
    factory
    其實就是個函式;用來建立一個類別 (class) 或是物件 (object) 的函式,在物件導向的程式語言中有個特殊的名字,叫 factory。這個函式裡,便撰寫建立一個類別或物件的程式,這個函式一定要傳回一個參考值,否則其它模組或程式就沒有辦法使用這個模組了。

建立模組時,要先在檔案系統裡依照模組的分類及彼此間的關係建立目錄結構,以便將來載入及維護。

/* content in file js/app/Person.js */
define([
    "dojo/_base/declare"
    ],
function(
    declare
){
    var Person = declare(null, {
        constructor: function(name, age, residence){
            this.name = name;
            this.age = age;
            this.residence = residence;
            Person.count++;
        }
    });
    Person.count = 0;    // class variable
    return Person;
});

在 js/app/Person.js 這個檔案中,撰寫了一個名為 Person 的類別,因為要給予一個類別變數,所以先將類別指派給一個變數,定義完類別變數後,才將變數傳出去。這裡正好變數的名稱也取名為 Person,其實取什麼名字都可以。

第一個參數從缺,所以會用檔案的名稱做為模組的名稱。因為函式中用到了 dojo 的 declare() 函式,也就是這個模組和 "dojo/_base/declare" 這個模組有相依性,因此要相依模組的陣列中列出這個模組的名稱。隨後就是宣告類別,並傳回類別的參考值。

/* content in file js/app/Employee.js */
define([
    "dojo/_base/declare",
    "app/Person"
    ],
function(
    declare,
    Person
){
    return declare(Person, {
        constructor: function(name, age, residence, salary){
            this.salary = salary;
        },
        askForRaise:function(){
            return this.salary * 0.02;
        }
    });
});

在 js/app/Employee.js 中,則建立名為 Employee 的類別,因為 Employee 繼承了 Person,所以在相依模組的陣列中,也將 Person 模組列入。

/* content in file js/app/Boss.js */
define([
    "dojo/_base/declare",
    "app/Employee"
    ],
function(
    declare,
    Employee
){
    return declare(Employee, {
        askForRaise:function(){
            return this.inherited(arguments) * 2; // calling parent's method, also modify the method
        }
    });
});

在 js/app/Boss.js 中則建立名為 Boss 的類別,因為 Boss 繼承了 Employee,所以在相依模組的陣列中,也列入 Employee。雖然 Employee 和 Person 也有相依,但在此處無需列入 Person,載入器在載入 Employee 模組時,會自行依照 Employee 類別相依陣列的內容,加載 Person 模組。

在使用這些自定的模組時,要記得在 dojoConfig 中定義模組在檔案系統中放置的位置。




只要定義好自定模組在系統中的位置,在使用這些模組時,就和使用 dojo 的模組沒有什麼兩樣了。

沒有留言:

張貼留言