前端開發 HTML5 CSS3 HTML CSS JavaScript jQuery Bootstrap

RequireJS介紹及入門

jQuery HTML我幫您 1年前  690次瀏覽
如今最常用的JavaScript庫之一是RequireJS(http://requirejs.org/)。最近我參與的每個項目,都用到了RequireJS,或者是我向它們推薦了增加RequireJS。在這篇文章中,我將描述RequireJS是什么,以及它的一些基礎場景。
異步模塊定義(AMD)

談起RequireJS,你無法繞過提及JavaScript模塊是什么,以及AMD是什么。

JavaScript模塊只是遵循SRP(Single Responsibility Principle單一職責原則)的代碼段,它暴露了一個公開的API。在現今JavaScript開發中,你可以在模塊中封裝許多功能,而且在大多數項目中,每個模塊都有其自己的文件。這使得JavaScript開發者日子有點難過,因為它們需要持續不斷的關注模塊之間的依賴性,按照一個特定的順序加載這些模塊,否則運行時將會放生錯誤。

基于 AMD(Asynchronous Module Definition)的 JavaScript 設計已經在目前較為流行的前端框架中大行其道,jQuery、Dojo、MooTools、EmbedJS 等紛紛在其最新版本中加入了對 AMD 的支持。本文介紹的是另一款較為精簡的 RequireJS 框架,既想使用 AMD 的特性又不想引入一個龐大的庫的開發人員,不妨試試 RequireJS。RequireJS 可以幫助用戶異步按需的加載 JavaScript 代碼,并解決 JavaScript 模塊間的依賴關系,提升了前端代碼的整體質量和性能。

前端開發在近一兩年發展的非常快,JavaScript 作為主流的開發語言得到了前所未有的熱捧。大量的前端框架出現了,這些框架都在嘗試著解決一些前端開發中的共性問題,但是實現又不盡相同。在這個背景下,CommonJS 社區誕生了,為了讓前端框架發展的更加成熟,CommonJS 鼓勵開發人員一起在社區里為一些完成特定功能的框架制定規范。AMD(Asynchronous Module Definition)就是其中的一個規范。
傳統 JavaScript 代碼的問題

讓我們來看看一般情況下 JavaScript 代碼是如何開發的:通過


require 方法里的這個字符串數組參數可以允許不同的值,當字符串是以”.js”結尾,或者以”/”開頭,或者就是一個 URL 時,RequireJS 會認為用戶是在直接加載一個 JavaScript 文件,否則,當字符串是類似”my/module”的時候,它會認為這是一個模塊,并且會以用戶配置的 baseUrl 和 paths 來加載相應的模塊所在的 JavaScript 文件。配置的部分會在稍后詳細介紹。

這里要指出的是,RequireJS 默認情況下并沒有保證 myFunctionA 和 myFunctionB 一定是在頁面加載完成以后執行的,在有需要保證頁面加載以后執行腳本時,RequireJS 提供了一個獨立的 domReady 模塊,需要去 RequireJS 官方網站下載這個模塊,它并沒有包含在 RequireJS 中。有了 domReady 模塊,清單 2 的代碼稍做修改加上對 domReady 的依賴就可以了。
清單 3. 頁面加載后執行 JavaScript




執行清單 3 的代碼后,通過 Firebug 可以看到 RequireJS 會在當前的頁面上插入為 a.js 和 b.js 分別聲明了一個

使用 RequireJS 來定義 JavaScript 模塊

這里的 JavaScript 模塊與傳統的 JavaScript 代碼不一樣的地方在于它無須訪問全局的變量。模塊化的設計使得 JavaScript 代碼在需要訪問”全局變量”的時候,都可以通過依賴關系,把這些”全局變量”作為參數傳遞到模塊的實現體里,在實現中就避免了訪問或者聲明全局的變量或者函數,有效的避免大量而且復雜的命名空間管理。

如同 CommonJS 的 AMD 規范所述,定義 JavaScript 模塊是通過 define 方法來實現的。

下面我們先來看一個簡單的例子,這個例子通過定義一個 student 模塊和一個 class 模塊,在主程序中實現創建 student 對象并將 student 對象放到 class 中去。
清單 5. student 模塊,student.js

define(function(){
return {
createStudent: function(name, gender){
return {
name: name,
gender: gender
};
}
};
});

清單 6. class 模塊,class.js

define(function() {
var allStudents = <>;
return {
classID: "001",
department: "computer",
addToClass: function(student) {
allStudents.push(student);
},
getClassSize: function() {
return allStudents.length;
}
};
}
);

清單 7. 主程序

require(<"js/student", "js/class">, function(student, clz) {
clz.addToClass(student.createStudent("Jack", "male"));
clz.addToClass(student.createStudent("Rose", "female"));
console.log(clz.getClassSize()); // 輸出 2
});

student 模塊和 class 模塊都是獨立的模塊,下面我們再定義一個新的模塊,這個模塊依賴 student 和 class 模塊,這樣主程序部分的邏輯也可以包裝進去了。
清單 8. 依賴 student 和 class 模塊的 manager 模塊,manager.js

define(<"js/student", "js/class">, function(student, clz){
return {
addNewStudent: function(name, gender){
clz.addToClass(student.createStudent(name, gender));
},
getMyClassSize: function(){
return clz.getClassSize();
}
};
});

清單 9. 新的主程序

require(<"js/manager">, function(manager) {
manager.addNewStudent("Jack", "male");
manager.addNewStudent("Rose", "female");
console.log(manager.getMyClassSize());// 輸出 2
});

通過上面的代碼示例,我們已經清楚的了解了如何寫一個模塊,這個模塊如何被使用,模塊間的依賴關系如何定義。還是有一些使用技巧需要提示一下:

盡量不要提供模塊的 ID,如 AMD 規范所述,這個 ID 是可選項,如果提供了,在 RequireJS 的實現中會影響模塊的可遷移性,文件位置變化會導致需要手動修改該 ID。
每個 JavaScript 文件只定義一個模塊,模塊名稱和文件路徑的查找算法決定了這種方式是最優的,多個的模塊和文件會被優化器進行優化。
避免模塊的循環依賴,如果實在避免不了,可以模塊中加上對”require”模塊的依賴,在代碼中直接用 require(”dependencyModuleName”)。

配置 RequireJS

前面的介紹中,我們似乎忽略了一個基本問題,模塊名字是怎么來的?當我在 require 一個模塊時,這個模塊是如何映射到具體的 JavaScript 文件上去?這就涉及到如何配置 RequireJS。

最簡化的加載 RequireJS 的方式如清單 2 所示,在這種情況下,我們沒有指定一個 baseUrl 和 paths 給 RequireJS,如果通過如清單 10 所示方式,則 data-main 指定了一個在當前 index.html 目錄并行的文件夾下的 /js/main.js 作為程序入口,而 /js 目錄也將作為 baseUrl 在其他模塊定義時候使用。
清單 10. 載入 require.js



因此,我們前面示例中的所有模塊依賴,都可以去掉”js/”,直接寫 ”student”, ”class”,”manager” 等。

一種更為直接的方式顯示指定 baseUrl 和 paths 就是利用 require.config 來設置這些參數。如清單 11 所示。
清單 11. 配置 RequireJS




baseUrl指明的是所有模塊的 base URL,比如”my/module”所加載的 script實際上就是 /js/my/module.js。注意,以 .js 結尾的文件加載時不會使用該 baseUrl,它們仍然會使用當前 index.html所在的相對路徑來加載,所以仍然要加上”./js/”。如果 baseUrl沒有指定,那么就會使用 data-main中指定的路徑。

paths 中定義的路徑是用于替換模塊中的路徑,如上例中的 some/module 具體的 JavaScript 文件路徑是 /js/some/v1/module.js 。

waitSeconds 是指定最多花多長等待時間來加載一個 JavaScript 文件,用戶不指定的情況下默認為 7 秒。

另外一個重要的配置是 packages,它可以指定其他符合 CommonJS AMD 規范的目錄結構,由此帶來了豐富的擴展性。如 Dojo、jQuery 等的模塊也可以通過該配置來讓 RequireJS 加載。

其他可配置的選項還包括 locale、context、deps、callback等,有興趣的讀者可以在 RequireJS 的官方網站查閱相關文檔。

版權所有

發表評論

腾讯彩票兑奖