使用RequireJS庫(kù)加載JavaScript模塊的實(shí)例教程
js通過(guò)script標(biāo)簽的默認(rèn)加載方式是同步的,即第一個(gè)script標(biāo)簽內(nèi)的js加載完成后,才開(kāi)始加載第二個(gè),以此類推,直至js文件全部加載完畢。且js的依賴關(guān)系必須通過(guò)script的順序才能確保;而在js加載期間,瀏覽器將停止響應(yīng),這大大影響了用戶體驗(yàn),基于此,很多解決js以來(lái)和加載的方案出現(xiàn),require js就是其中之一。
requirejs加載的模塊,一般為符合AMD標(biāo)準(zhǔn)的模塊,即用define定義,用ruturn返回暴露方法、變量的模塊;requirejs也可以加載飛AMD標(biāo)準(zhǔn)的模塊,但比較麻煩,這次不涉及。
require加載js主涉及以下方面:
- script 標(biāo)簽data-main屬性聲明requirejs加載的入口模塊,async="true"(非ie) 和defer(ie)標(biāo)簽表明異步加載。
- require.config配置模塊對(duì)應(yīng)的路徑
- require聲明依賴關(guān)系
html demo
<script src ="js/require.js" defer async="true" data-main="js/main" > <!--給出requirejs路徑,聲明為異步加載,指定入口模塊為 main.js(可省略.js)-->
main.js
require.config({
//聲明模塊的位置
paths: {
"jquery":"libs/jquery"
"login" : "libs/login"
}
//或使用baseUrl指定所有模塊的路徑
baseUrl: "js/libs"
});
//使用require加載模塊,第一個(gè)參數(shù)為數(shù)組,即要加載的模塊,將按數(shù)組順序加載;第二個(gè)為回調(diào)函數(shù),在全部加載完成后執(zhí)行。
require(['jquery','login'],function($,Login){
alert("jquery and login module load success!");
Login.do_login();
//some else
});
符合amd的login module定義
//依賴jquery的定義
define(['jquery'],function($){
// some definations
function do_login(){
$.post('/sessions/create',{uname:$("#uname").val(),
password:$("#password").val()},function(data){
//some
});
return {do_login:do_login};
}
});
//不依賴其他模塊的定義
define(function(){
//some definations
return {xx:xx};
});
rails沒(méi)有應(yīng)用js加載器,一方面是新版本的rails的asset pipe會(huì)將所有的js文件打包為一個(gè)js文件,沒(méi)有多個(gè)js加載的狀態(tài),另一方面turbolink使用褒貶參半的所謂pjax技術(shù),默認(rèn)鏈接改為ajax方式,只獲取html的bod部分,head部分不變動(dòng),使js的加載只在第一次打開(kāi)網(wǎng)站時(shí)進(jìn)行。
案例一: 加載 JavaScript 文件
<script src="./js/require.js"></script>
<script>
require(["./js/a.js", "./js/b.js"], function() {
myFunctionA();
myFunctionB();
});
</script>
require 方法里的這個(gè)字符串?dāng)?shù)組參數(shù)可以允許不同的值,當(dāng)字符串是以”.js”結(jié)尾,或者以”/”開(kāi)頭,或者就是一個(gè) URL 時(shí),RequireJS 會(huì)認(rèn)為用戶是在直接加載一個(gè) JavaScript 文件,否則,當(dāng)字符串是類似”my/module”的時(shí)候,它會(huì)認(rèn)為這是一個(gè)模塊,并且會(huì)以用戶配置的 baseUrl 和 paths 來(lái)加載相應(yīng)的模塊所在的 JavaScript 文件。配置的部分會(huì)在稍后詳細(xì)介紹。
這里要指出的是,RequireJS 默認(rèn)情況下并沒(méi)有保證 myFunctionA 和 myFunctionB 一定是在頁(yè)面加載完成以后執(zhí)行的,在有需要保證頁(yè)面加載以后執(zhí)行腳本時(shí),RequireJS 提供了一個(gè)獨(dú)立的 domReady 模塊,需要去 RequireJS 官方網(wǎng)站下載這個(gè)模塊,它并沒(méi)有包含在 RequireJS 中。有了 domReady 模塊,案例一 的代碼稍做修改加上對(duì) domReady 的依賴就可以了。
案例二: 頁(yè)面加載后執(zhí)行 JavaScript
<script src="./js/require.js"></script>
<script>
require(["domReady!", "./js/a.js", "./js/b.js"], function() {
myFunctionA();
myFunctionB();
});
</script>
執(zhí)行案例二的代碼后,通過(guò) Firebug 可以看到 RequireJS 會(huì)在當(dāng)前的頁(yè)面上插入為 a.js 和 b.js 分別聲明了一個(gè) < script> 標(biāo)簽,用于異步方式下載 JavaScript 文件。async 屬性目前絕大部分瀏覽器已經(jīng)支持,它表明了這個(gè) < script> 標(biāo)簽中的 js 文件不會(huì)阻塞其他頁(yè)面內(nèi)容的下載。
案例三:RequireJS 插入的 < script>
<script type="text/javascript" charset="utf-8" async="" data-requirecontext="_" data-requiremodule="js/a.js" src="js/a.js"></script>
使用 RequireJS 來(lái)定義 JavaScript 模塊
這里的 JavaScript 模塊與傳統(tǒng)的 JavaScript 代碼不一樣的地方在于它無(wú)須訪問(wèn)全局的變量。模塊化的設(shè)計(jì)使得 JavaScript 代碼在需要訪問(wèn)”全局變量”的時(shí)候,都可以通過(guò)依賴關(guān)系,把這些”全局變量”作為參數(shù)傳遞到模塊的實(shí)現(xiàn)體里,在實(shí)現(xiàn)中就避免了訪問(wèn)或者聲明全局的變量或者函數(shù),有效的避免大量而且復(fù)雜的命名空間管理。
如同 CommonJS 的 AMD 規(guī)范所述,定義 JavaScript 模塊是通過(guò) define 方法來(lái)實(shí)現(xiàn)的。
下面我們先來(lái)看一個(gè)簡(jiǎn)單的例子,這個(gè)例子通過(guò)定義一個(gè) student 模塊和一個(gè) class 模塊,在主程序中實(shí)現(xiàn)創(chuàng)建 student 對(duì)象并將 student 對(duì)象放到 class 中去。
案例四: student 模塊,student.js
define(function(){
return {
createStudent: function(name, gender){
return {
name: name,
gender: gender
};
}
};
});
案例五:class 模塊,class.js
define(function() {
var allStudents = [];
return {
classID: "001",
department: "computer",
addToClass: function(student) {
allStudents.push(student);
},
getClassSize: function() {
return allStudents.length;
}
};
}
);
案例六: 主程序
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 模塊都是獨(dú)立的模塊,下面我們?cè)俣x一個(gè)新的模塊,這個(gè)模塊依賴 student 和 class 模塊,這樣主程序部分的邏輯也可以包裝進(jìn)去了。
案例七: 依賴 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();
}
};
});
案例八:新的主程序
require(["js/manager"], function(manager) {
manager.addNewStudent("Jack", "male");
manager.addNewStudent("Rose", "female");
console.log(manager.getMyClassSize());// 輸出 2
});
通過(guò)上面的代碼示例,我們已經(jīng)清楚的了解了如何寫(xiě)一個(gè)模塊,這個(gè)模塊如何被使用,模塊間的依賴關(guān)系如何定義。還是有一些使用技巧需要提示一下:
盡量不要提供模塊的 ID,如 AMD 規(guī)范所述,這個(gè) ID 是可選項(xiàng),如果提供了,在 RequireJS 的實(shí)現(xiàn)中會(huì)影響模塊的可遷移性,文件位置變化會(huì)導(dǎo)致需要手動(dòng)修改該 ID。
每個(gè) JavaScript 文件只定義一個(gè)模塊,模塊名稱和文件路徑的查找算法決定了這種方式是最優(yōu)的,多個(gè)的模塊和文件會(huì)被優(yōu)化器進(jìn)行優(yōu)化。 避免模塊的循環(huán)依賴,如果實(shí)在避免不了,可以模塊中加上對(duì)”require”模塊的依賴,在代碼中直接用
require(”dependencyModuleName”)
配置 RequireJS:
前面的介紹中,我們似乎忽略了一個(gè)基本問(wèn)題,模塊名字是怎么來(lái)的?當(dāng)我在 require 一個(gè)模塊時(shí),這個(gè)模塊是如何映射到具體的 JavaScript 文件上去?這就涉及到如何配置 RequireJS。
最簡(jiǎn)化的加載 RequireJS 的方式如案例2 所示,在這種情況下,我們沒(méi)有指定一個(gè) baseUrl 和 paths 給 RequireJS,如果通過(guò)如案例10 所示方式,則 data-main 指定了一個(gè)在當(dāng)前 index.html 目錄并行的文件夾下的 /js/main.js 作為程序入口,而 /js 目錄也將作為 baseUrl 在其他模塊定義時(shí)候使用。
案例九:載入 require.js
<script data-main="js/main" src="scripts/require.js"></script>
因此,我們前面示例中的所有模塊依賴,都可以去掉”js/”,直接寫(xiě) ”student”, ”class”,”manager” 等。 一種更為直接的方式顯示指定 baseUrl 和 paths 就是利用 require.config 來(lái)設(shè)置這些參數(shù)。如案例十 所示。
案例十. 配置 RequireJS
<script type="text/javascript" src="./js/require.js"></script>
<script type="text/javascript">
require.config({
baseUrl: "./js",
paths: {
"some": "some/v1"
},
waitSeconds: 10
});
require( ["some/module", "my/module", "./js/a.js"],
function(someModule, myModule) {}
);
</script>
baseUrl指明的是所有模塊的 base URL,比如”my/module”所加載的 script實(shí)際上就是 /js/my/module.js。注意,以 .js 結(jié)尾的文件加載時(shí)不會(huì)使用該 baseUrl,它們?nèi)匀粫?huì)使用當(dāng)前 index.html所在的相對(duì)路徑來(lái)加載,所以仍然要加上”./js/”。如果 baseUrl沒(méi)有指定,那么就會(huì)使用 data-main中指定的路徑。
paths 中定義的路徑是用于替換模塊中的路徑,如上例中的 some/module 具體的 JavaScript 文件路徑是 /js/some/v1/module.js 。 waitSeconds 是指定最多花多長(zhǎng)等待時(shí)間來(lái)加載一個(gè) JavaScript 文件,用戶不指定的情況下默認(rèn)為 7 秒。
另外一個(gè)重要的配置是 packages,它可以指定其他符合 CommonJS AMD 規(guī)范的目錄結(jié)構(gòu),由此帶來(lái)了豐富的擴(kuò)展性。如 Dojo、jQuery 等的模塊也可以通過(guò)該配置來(lái)讓 RequireJS 加載。
其他可配置的選項(xiàng)還包括 locale、context、deps、callback等,有興趣的讀者可以在 RequireJS 的官方網(wǎng)站查閱相關(guān)文檔。
- 一篇文章掌握RequireJS常用知識(shí)
- 教你5分鐘學(xué)會(huì)用requirejs(必看篇)
- RequireJS入門(mén)一之實(shí)現(xiàn)第一個(gè)例子
- RequireJS多頁(yè)面應(yīng)用實(shí)例分析
- 在Html中使用Requirejs進(jìn)行模塊化開(kāi)發(fā)實(shí)例詳解
- RequireJS使用注意細(xì)節(jié)
- 使用requirejs模塊化開(kāi)發(fā)多頁(yè)面一個(gè)入口js的使用方式
- requirejs + vue 項(xiàng)目搭建詳解
- 在JavaScript應(yīng)用中使用RequireJS來(lái)實(shí)現(xiàn)延遲加載
- 詳解RequireJS按需加載樣式文件
- RequireJS用法簡(jiǎn)單示例
相關(guān)文章
Three.js學(xué)習(xí)之Lamber材質(zhì)和Phong材質(zhì)
本篇將介紹基本材質(zhì)以及兩種基于光照模型的材質(zhì)(Lamber與Phong),有需要的小伙伴們可以參考學(xué)習(xí)。2016-08-08
Highcharts學(xué)習(xí)之坐標(biāo)軸
今天講交互圖表Highcharts的坐標(biāo)軸,我們將對(duì)Highcharts圖表的坐標(biāo)軸組成、坐標(biāo)軸類型等進(jìn)行詳細(xì)系統(tǒng)講解。下面一起來(lái)看看。2016-08-08
精通JavaScript 糾正 cleanWhitespace函數(shù)
這個(gè)函數(shù)用在火狐(firefox)上面老是出錯(cuò),今天仔細(xì)研究了下,改正了,希望別人不要遇到我這樣的問(wèn)題2010-03-03
JS日程管理插件FullCalendar簡(jiǎn)單實(shí)例
JS日程管理插件FullCalendar是一款基于jQuery的日歷日程插件,適用于各種日程安排、工作計(jì)劃等場(chǎng)景,您可以很方便的查看查看待辦事項(xiàng),標(biāo)記重要事項(xiàng)以及綁定點(diǎn)擊和拖動(dòng)事件,能快速的整合到您的項(xiàng)目中,本文將簡(jiǎn)單介紹FullCalendar的使用2017-02-02
js類庫(kù)styled-components快速入門(mén)教程
這篇文章主要為大家介紹了js類庫(kù)styled-components快速入門(mén)的教程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
Three.js學(xué)習(xí)之文字形狀及自定義形狀
今天小編帶大家學(xué)習(xí)的是Three.js的文字形狀與自定義形狀,文章內(nèi)容很詳細(xì),對(duì)大家學(xué)習(xí)Three.js或許有幫助,下面一起來(lái)看看吧。2016-08-08

