Requirejs常用配置和應(yīng)用

requirejs、require方法沖突

如果加載了多個(gè)requirejs腳本雹食,每個(gè)requirejs會(huì)判斷是否瀏覽器已經(jīng)實(shí)現(xiàn)了require和define方法。如果瀏覽器已經(jīng)自帶require和define方法,或者之前已經(jīng)有一個(gè)requirejs腳本執(zhí)行茸习,那么這個(gè)requirejs就會(huì)立刻停止執(zhí)行。所以壁肋,即使頁面上加載了多次requirejs腳本也不會(huì)有什么問題号胚。

配置Context

我把context叫做一個(gè)命名空間,因?yàn)槊恳粋€(gè)context都有一個(gè)名字浸遗,這樣同名而功能不同的模塊就可以放在不同的context中以防沖突猫胁。

如果開發(fā)人員沒有配置context,那么跛锌,requirejs還會(huì)生成一個(gè)默認(rèn)的context弃秆,這個(gè)默認(rèn)的context配置大致如下:

requirejs.config({

context: "_",? // default context name

baseUrl: "./",

waitSeconds:7, // how long canloading last

paths: {},

bundles: {},

pkgs: {},

shim: {},

config: {}

});

注意:在不指定context名稱的情況下,任何配置和調(diào)用都是針對默認(rèn)context的修改和調(diào)用。

空間名稱 – context

如果requirejs初始化時(shí)自定義配置context菠赚,那么默認(rèn)創(chuàng)建的context的name 就是”_”盼樟。如果需要添加新的context,只需指定一個(gè)新的contextName即可锈至,比如下面這個(gè)調(diào)用就會(huì)創(chuàng)建一個(gè)新的context:

requirejs({context:”new content name”});

同名的context只會(huì)有一個(gè)晨缴,配置同名的context等于修改這個(gè)context的屬性。

加載超時(shí) – waitSeconds

每個(gè)context都配置了一個(gè)加載超時(shí)的時(shí)間峡捡,某個(gè)模塊如果沒有初始化击碗,加載的時(shí)間又超過了這個(gè)時(shí)間,就會(huì)被認(rèn)為加載失敗们拙。

加載超時(shí)是針對整個(gè)context下的所有模塊而言的稍途,而不是單指某個(gè)模塊,也就是說這個(gè)默認(rèn)的7秒是指所有模塊應(yīng)該在7秒之內(nèi)全部加載完成砚婆。7秒之后械拍,如果有沒有被加載的模塊,將拋出error指示哪些模塊沒有加載装盯。(requirejs每隔50毫秒做一次判斷)坷虑。

基準(zhǔn)URL – baseUrl

每個(gè)context的基準(zhǔn)URL默認(rèn)值是”./”。

第一個(gè)context的基準(zhǔn)URL

如果開發(fā)人員沒有指定context名稱埂奈,那么這個(gè)第一個(gè)context就是requirejs默認(rèn)生成的context迄损,否則就是開發(fā)人員自己定義的context。在不指定基準(zhǔn)URL的前提下账磺,第一個(gè)context的基準(zhǔn)URL設(shè)定比較特殊芹敌,除了標(biāo)準(zhǔn)的設(shè)定方法(參考后面的基準(zhǔn)URL標(biāo)準(zhǔn)設(shè)定方法),還可以使用以下兩種特殊方式設(shè)置:

第一種:通過requirejs或require對象配置

在確認(rèn)requirejs腳本之前沒有其它requirejs執(zhí)行過的前提下:

requirejs={baseUrl: './'}

require={baseUrl: './'}

注意:通過這種方式設(shè)置基準(zhǔn)URL垮抗,data-main指定的腳本文件位置也會(huì)變成相對于基準(zhǔn)URL的路徑氏捞,因?yàn)閐ata-main指定的腳本本身只是依賴的關(guān)系之一。而且冒版,data-main指定的腳本也屬于第一個(gè)context液茎。

比如下面這種情況:

requirejs={baseUrl: 'scripts/lib'}

腳本模塊app.js的最終路徑變成了"scripts/lib/scripts/app.js",不是原來的"scripts/app.js"壤玫,而且它的依賴名稱也會(huì)變?yōu)閟cripts/lib/scripts/app(requirejs默認(rèn)會(huì)去掉腳本路徑的最后一個(gè)“.js”豁护,除非data-main的值以“/”開頭哼凯,或包含“:”欲间,或包含“?”)

第二種:根據(jù)script元素的data-main屬性指定的腳本路徑計(jì)算

如果沒有設(shè)定baseUrl断部,requirejs會(huì)根據(jù)script元素data-main屬性指定的JavaScript文件路徑計(jì)算出一個(gè)基準(zhǔn)URL猎贴。

比如data-main="scripts/app.js",那么baseUrl就是"scripts/":

基準(zhǔn)URL標(biāo)準(zhǔn)設(shè)定方法

除了第一個(gè)context可以使用上面的方法,其它自定義的context配置baseUrl就只能使用下面這兩種方法她渴。但這兩種方法同樣也可以用來修改第一個(gè)context的屬性达址,在不指定context名稱的情況下,其實(shí)就是修改第一個(gè)context趁耗。

通過requirejs或require方法(這兩個(gè)本身就是同一個(gè)方法)設(shè)置

以下兩個(gè)等于把默認(rèn)命名空間的基準(zhǔn)URL設(shè)置成了scripts/lib:

requirejs({baseUrl:'scripts/lib'});

require({baseUrl:'scripts/lib'});

通過requirejs.config方法

requirejs.config({baseUrl:'scripts/lib'});

require.config({baseUrl:'scripts/lib'});

其實(shí)config方法調(diào)用的就是requirejs方法沉唠,所以它們是一樣的。

模塊依賴 – deps

模塊依賴是指個(gè)模塊之間的相互依賴關(guān)系苛败,腳本運(yùn)行時(shí)满葛,只有當(dāng)依賴的模塊全部加載完成之后,當(dāng)前腳本才會(huì)執(zhí)行罢屈,這就是依賴關(guān)系的作用嘀韧。

依賴關(guān)系使用數(shù)組配置,數(shù)組元素為字符串(即模塊的名稱)缠捌,一般是相對于baseUrl的路徑锄贷,只不過沒有文件后綴。而且曼月,為了比較方便的獲取模塊入口谊却,模塊一般會(huì)通過define方法定義。因?yàn)檠魄郏ㄟ^define定義的模塊因惭,可以被依賴數(shù)組后面的回調(diào)函數(shù)直接獲取并使用。

以jQuery為例绩衷,在jQuery腳本的末尾一般有下面兩行代碼:

if(typeof define === "function"&& define.amd && define.amd.jQuery) {

define("jquery", [], function () { return jQuery; } );

}

再以underscore為例蹦魔,在腳本末尾有下面幾行代碼:

if (typeof define === 'function' && define.amd) {

define('underscore', [],function() {

return _;

});

}

模塊和模塊位置

使用require配置依賴模塊的時(shí)候,只是聲明了模塊的名稱咳燕,卻不知道模塊的具體位置勿决。在沒有特殊聲明的情況下,requirejs認(rèn)為模塊名和文件名相同招盲,因此低缩,只要兩者一致,requirejs就可以正確找到腳本文件曹货。但如果不同咆繁,就需要通過path配置:

requirejs.config({

baseUrl:"scripts/lib",

paths: {

jquery:'jquery-1.7.2'

}

});

這樣,requirejs就知道jquery模塊位于scripts/lib/jquery-1.7.2.js文件中顶籽。

第一個(gè)context的依賴關(guān)系

requirejs={deps: ['jquery']}

其它c(diǎn)ontext的依賴關(guān)系

與基準(zhǔn)URL的方式一樣玩般,既可以通過requirejs方法,也可通過requirejs.config方法配置礼饱。

模塊束-bundles

如果一個(gè)JS文件中有多個(gè)模塊坏为,就可以使用模塊束的方式聲明:

requirejs.config({

baseUrl:"scripts/lib",

bundles: {

jsUtil:['MathUtil', 'DateUtil']

}

});

上面這個(gè)例子就是說在scripts/lib/jsUtils.js文件中有MathUtil和DateUtil這兩個(gè)子模塊究驴。

JS包– packages

如果一個(gè)文件夾中有多個(gè)JS文件,使用path的方式寫全就需要很多行代碼匀伏,這個(gè)時(shí)候如果使用包的方式聲明就可以省去很多麻煩:

requirejs.config({

baseUrl:"scripts/lib",

pkgs: [{name:'jqueryui',location: 'jqueryui/',main: 'core'}]

});

這樣定義之后洒忧,凡是在scripts/lib/jqueryui/目錄下的模塊就可以通過這種方式正確找到:

require(['jqueryui/button', 'jqueryui/dialog']);

上面這個(gè)例子就是獲取scripts/lib/jqueryui/button.js和scripts/lib/jqueryui/dialog.js的例子。另外够颠,因?yàn)閖queryui是一個(gè)目錄熙侍,并不對應(yīng)一個(gè)JS文件,所以又有一個(gè)main屬性履磨,這個(gè)屬性一般對應(yīng)這個(gè)JS包中的主程序文件核行。上面的例子中,jqueryui的主程序就在scripts/lib/jqueryui/core.js中蹬耘。

楔子 – shim

并不是所有的JS模塊都會(huì)像jquery和underscore那樣調(diào)用define方法定義自己芝雪,這樣requirejs就不知道你這個(gè)模塊的入口在哪,該通過哪個(gè)對象來調(diào)用這個(gè)模塊综苔,特別是那些早版本的JS模塊惩系,因?yàn)槟鞘沁€沒有define和require的概念。

requirejs.config({

baseUrl:"scripts/lib",

shim: {jquery: {deps:[],exportsFn: func, exports:'jQuery',init:func}}

});

雖然模塊沒有使用define方法定義自己如筛,但開發(fā)人員應(yīng)該是知道如何獲取文件中的模塊的堡牡,所以,requirejs提供了兩種方式讓開發(fā)人員把模塊對象返回給requirejs管理:

在exportsFn或init方法中設(shè)置杨刨,然后作為返回值晤柄;

使用exports設(shè)置,比如”a.b.c”妖胀,那requirejs就知道通過window.a.b.c可以獲取芥颈。

映射 – Map

先來看問題:一些第三方JS插件的依賴關(guān)系是事先設(shè)定好的,不太好修改依賴模塊的名稱赚抡,而如果某個(gè)模塊有多個(gè)版本或有其他模塊和它同名爬坑,則使用上面的配置都無法解決問題。比如path只是解決模塊名稱到路徑的問題涂臣,而這個(gè)面對的是切換模塊名稱的問題盾计。于是requirejs提出了映射的概念,根據(jù)當(dāng)前腳本的名稱動(dòng)態(tài)修改所依賴模塊的ID赁遗,是它指向正確的模塊署辉。

假如在你的硬盤下有以下幾個(gè)模塊:

foo1.0.js

foo1.2.js

some/newmodule.js

some/oldmodule.js

在newmodule.js和oldmodule.js中都有require(‘foo’)調(diào)用,要解決沖突只需要這樣配置即可:

requirejs.config({

map: {

'some/newmodule':{

'foo': 'foo1.2'

},

'some/oldmodule':{

'foo':'foo1.0'

}

}

});

主程序入口data-main

不管頁面上有多少個(gè)script元素有data-main屬性岩四,requirejs只認(rèn)最后一個(gè)script元素的data-main屬性哭尝,忽略其他script元素的data-main屬性。

Requirejs獲取data-main屬性之后炫乓,并沒有立即執(zhí)行data-main指定的腳本文件(因?yàn)檫@個(gè)腳本文件可能還依賴了其他模塊)刚夺,而是把它作為了一個(gè)被依賴的模塊献丑,加入到第一個(gè)context的依賴數(shù)組中末捣。比如下面這種情況就是把scripts/app這個(gè)模塊加到一個(gè)名叫l(wèi)inus的context中:

requirejs={

context: 'linus',

baseUrl:"./",

skipDataMain: false

};

全局配置

忽略script元素的data-main

在瀏覽器中侠姑,有一個(gè)選項(xiàng)叫skipDataMain,可以讓requirejs忽略script元素的data-main箩做。在默認(rèn)情況下莽红,requirejs成功加載之后,會(huì)立馬查找頁面上所有script元素邦邦,并且把最后一個(gè)有data-main屬性的script元素的data-main最為主程序入口安吁。

requirejs={skipDataMain:true}

模塊定義 – define(name, deps, callback)

你會(huì)發(fā)現(xiàn)define方法沒有指定context名稱,這是因?yàn)閐efine方法只調(diào)用于被依賴的模塊中燃辖,而require方法已經(jīng)為依賴的模塊指定了context名稱鬼店,所以,這個(gè)模塊被哪個(gè)context需要黔龟,它就屬于那一個(gè)context妇智。

參數(shù)name是模塊的名稱,deps是該模塊所依賴的其他模塊的名稱氏身,callback一般返回該模塊的實(shí)際可被使用對象巍棱。比如jQuery的模塊定義回調(diào)函數(shù)返回的就是jQuery對象。

Error

加載Error

這種error就是瀏覽器自帶的Error對象蛋欣,只不過requirejs給它附加了其他屬性航徙。

message的格式為:msg + '\nhttp://requirejs.org/docs/errors.html#' + id。

error.requireType就是就是message后面的id陷虎;

error.requireModules一般指需要加載卻沒加載成功的模塊名稱到踏;

error.originalError是指發(fā)生其他錯(cuò)誤導(dǎo)致模塊加載失敗的原始error對象。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尚猿,一起剝皮案震驚了整個(gè)濱河市夭禽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谊路,老刑警劉巖讹躯,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異缠劝,居然都是意外死亡潮梯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門惨恭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秉馏,“玉大人寒砖,你說我怎么就攤上這事自沧∧笈颍” “怎么了廊酣?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長帆竹。 經(jīng)常有香客問我绕娘,道長,這世上最難降的妖魔是什么栽连? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任险领,我火速辦了婚禮,結(jié)果婚禮上秒紧,老公的妹妹穿的比我還像新娘绢陌。我一直安慰自己,他們只是感情好熔恢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布脐湾。 她就那樣靜靜地躺著,像睡著了一般叙淌。 火紅的嫁衣襯著肌膚如雪秤掌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天凿菩,我揣著相機(jī)與錄音机杜,去河邊找鬼。 笑死衅谷,一個(gè)胖子當(dāng)著我的面吹牛椒拗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播获黔,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蚀苛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了玷氏?” 一聲冷哼從身側(cè)響起堵未,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盏触,沒想到半個(gè)月后渗蟹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赞辩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年雌芽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辨嗽。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡世落,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出糟需,到底是詐尸還是另有隱情屉佳,我是刑警寧澤谷朝,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站武花,受9級特大地震影響圆凰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜髓堪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一送朱、第九天 我趴在偏房一處隱蔽的房頂上張望娘荡。 院中可真熱鬧干旁,春花似錦、人聲如沸炮沐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽大年。三九已至换薄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間翔试,已是汗流浹背轻要。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留垦缅,地道東北人冲泥。 一個(gè)月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像壁涎,于是被迫代替她去往敵國和親凡恍。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 導(dǎo)語: 之前一直有聽說RequireJS怔球,但是一直都沒機(jī)會(huì)去了解嚼酝,只知道它是一個(gè)給js做模塊化的API。最近在做R...
    wuqke閱讀 40,921評論 11 78
  • 參考資料 RequireJS 中文網(wǎng)Javascript模塊化編程(三):require.js的用法——阮一峰 前...
    BeYanJin閱讀 7,072評論 2 12
  • RequireJS路徑詳解(深入理解) 0. 前言 由于官方文檔說明甚少竟坛,導(dǎo)致RequireJS的路徑解析邏輯就像...
    大貓Kevin閱讀 9,370評論 1 11
  • 世人皆醒担汤,為我獨(dú)醉涎跨,人生何苦如此---sunnyhuang 題目1: 為什么要使用模塊化? 解決命名沖突 依賴管理...
    sunny519111閱讀 280評論 0 0
  • 大家好,我是IT修真院鄭州分院第四期的學(xué)員王相博驾荣,一枚正直純潔善良的WEB前端程序員外构。 今天給大家分享一下普泡,修真院...
    More_ce0d閱讀 302評論 0 0