最近花了一點(diǎn)時(shí)間對(duì)seajs進(jìn)行了了解。
一、seajs
seajs是cmd(Common Module Definition)的模塊加載框架,說(shuō)白了就是在前端開(kāi)發(fā)中
如何定義一個(gè)js文件磺陡,如何在項(xiàng)目中引入這個(gè)js文件兢交。
二、基于cmd就對(duì)cmd進(jìn)行了解
1锭沟、cmd是一種模塊定義的規(guī)范
常使用的 API 只有?define,?require,?require.async,?exports,module.exports?這五個(gè)
2抽兆、這個(gè)規(guī)范的內(nèi)容是什么?參考:https://github.com/seajs/seajs/issues/242
在 CMD 規(guī)范中族淮,一個(gè)模塊就是一個(gè)文件辫红。代碼的書寫格式如下:
define(factory);
define?Function
define?是一個(gè)全局函數(shù),用來(lái)定義模塊祝辣。
define?define(factory)
define?接受?factory?參數(shù)贴妻,factory?可以是一個(gè)函數(shù),也可以是一個(gè)對(duì)象或字符串较幌。
factory?為對(duì)象揍瑟、字符串時(shí),表示模塊的接口就是該對(duì)象乍炉、字符串绢片。比如可以如下定義一個(gè) JSON 數(shù)據(jù)模塊:
define({"foo":"bar"});
也可以通過(guò)字符串定義模板模塊:
define('I am a template. My name is {{name}}.');
factory?為函數(shù)時(shí),表示是模塊的構(gòu)造方法岛琼。執(zhí)行該構(gòu)造方法底循,可以得到模塊向外提供的接口。factory?方法在執(zhí)行時(shí)槐瑞,默認(rèn)會(huì)傳入三個(gè)參數(shù):require熙涤、exports?和?module:
define(function(require,exports,module) {//模塊代碼});
define?define(id?, deps?, factory)
define?也可以接受兩個(gè)以上參數(shù)。字符串?id?表示模塊標(biāo)識(shí),數(shù)組?deps?是模塊依賴祠挫。比如:
define('hello', ['jquery'],function(require,exports,module) {//模塊代碼});
id?和?deps?參數(shù)可以省略那槽。省略時(shí),可以通過(guò)構(gòu)建工具自動(dòng)生成等舔。
注意:帶?id?和?deps?參數(shù)的?define?用法不屬于 CMD 規(guī)范骚灸,而屬于?Modules/Transport?規(guī)范。
define.cmd?Object
一個(gè)空對(duì)象慌植,可用來(lái)判定當(dāng)前頁(yè)面是否有 CMD 模塊加載器:
if(typeofdefine==="function"&&define.cmd) {//有 Sea.js 等 CMD 模塊加載器存在}
require?Function
require?是?factory?函數(shù)的第一個(gè)參數(shù)甚牲。
require?require(id)
require?是一個(gè)方法,接受?模塊標(biāo)識(shí)?作為唯一參數(shù)蝶柿,用來(lái)獲取其他模塊提供的接口丈钙。
define(function(require,exports) {//獲取模塊 a 的接口vara=require('./a');//調(diào)用模塊 a 的方法a.doSomething();});
注意:在開(kāi)發(fā)時(shí),require?的書寫需要遵循一些?簡(jiǎn)單約定交汤。
require.async?require.async(id, callback?)
require.async?方法用來(lái)在模塊內(nèi)部異步加載模塊雏赦,并在加載完成后執(zhí)行指定回調(diào)。callback?參數(shù)可選蜻展。
define(function(require,exports,module) {//異步加載一個(gè)模塊喉誊,在加載完成時(shí),執(zhí)行回調(diào)require.async('./b',function(b) {b.doSomething();? });//異步加載多個(gè)模塊纵顾,在加載完成時(shí),執(zhí)行回調(diào)require.async(['./c','./d'],function(c,d) {c.doSomething();d.doSomething();? });});
注意:require?是同步往下執(zhí)行栋盹,require.async?則是異步回調(diào)執(zhí)行施逾。require.async?一般用來(lái)加載可延遲異步加載的模塊。
require.resolve?require.resolve(id)
使用模塊系統(tǒng)內(nèi)部的路徑解析機(jī)制來(lái)解析并返回模塊路徑例获。該函數(shù)不會(huì)加載模塊汉额,只返回解析后的絕對(duì)路徑。
define(function(require,exports) {console.log(require.resolve('./b'));//==> http://example.com/path/to/b.js});
這可以用來(lái)獲取模塊路徑榨汤,一般用在插件環(huán)境或需動(dòng)態(tài)拼接模塊路徑的場(chǎng)景下蠕搜。
exports?Object
exports?是一個(gè)對(duì)象,用來(lái)向外提供模塊接口收壕。
define(function(require,exports) {//對(duì)外提供 foo 屬性exports.foo='bar';//對(duì)外提供 doSomething 方法exports.doSomething=function() {};});
除了給?exports?對(duì)象增加成員妓灌,還可以使用?return?直接向外提供接口。
define(function(require) {//通過(guò) return 直接提供接口return{? ? foo:'bar',doSomething:function() {}? };});
如果?return?語(yǔ)句是模塊中的唯一代碼蜜宪,還可簡(jiǎn)化為:
define({? foo:'bar',doSomething:function() {}});
上面這種格式特別適合定義 JSONP 模塊虫埂。
特別注意:下面這種寫法是錯(cuò)誤的!
define(function(require,exports) {//錯(cuò)誤用法F匝椤掉伏!!exports={? ? foo:'bar',doSomething:function() {}? };});
正確的寫法是用?return?或者給?module.exports?賦值:
define(function(require,exports,module) {//正確寫法module.exports={? ? foo:'bar',doSomething:function() {}? };});
提示:exports?僅僅是?module.exports?的一個(gè)引用。在?factory?內(nèi)部給?exports?重新賦值時(shí),并不會(huì)改變?module.exports?的值斧散。因此給?exports?賦值是無(wú)效的供常,不能用來(lái)更改模塊接口。
module?Object
module?是一個(gè)對(duì)象鸡捐,上面存儲(chǔ)了與當(dāng)前模塊相關(guān)聯(lián)的一些屬性和方法话侧。
module.id?String
模塊的唯一標(biāo)識(shí)。
define('id', [],function(require,exports,module) {//模塊代碼});
上面代碼中闯参,define?的第一個(gè)參數(shù)就是模塊標(biāo)識(shí)瞻鹏。
module.uri?String
根據(jù)模塊系統(tǒng)的路徑解析規(guī)則得到的模塊絕對(duì)路徑。
define(function(require,exports,module) {console.log(module.uri);//==> http://example.com/path/to/this/file.js});
一般情況下(沒(méi)有在?define?中手寫?id?參數(shù)時(shí))鹿寨,module.id?的值就是?module.uri新博,兩者完全相同。
module.dependencies?Array
dependencies?是一個(gè)數(shù)組脚草,表示當(dāng)前模塊的依賴赫悄。
module.exports?Object
當(dāng)前模塊對(duì)外提供的接口。
傳給?factory?構(gòu)造方法的?exports?參數(shù)是?module.exports?對(duì)象的一個(gè)引用馏慨。只通過(guò)?exports?參數(shù)來(lái)提供接口埂淮,有時(shí)無(wú)法滿足開(kāi)發(fā)者的所有需求。 比如當(dāng)模塊的接口是某個(gè)類的實(shí)例時(shí)写隶,需要通過(guò)?module.exports來(lái)實(shí)現(xiàn):
define(function(require,exports,module) {//exports 是 module.exports 的一個(gè)引用console.log(module.exports===exports);//true//重新給 module.exports 賦值module.exports=newSomeClass();//exports 不再等于 module.exportsconsole.log(module.exports===exports);//false});
注意:對(duì)?module.exports?的賦值需要同步執(zhí)行倔撞,不能放在回調(diào)函數(shù)里。下面這樣是不行的:
//x.jsdefine(function(require,exports,module) {//錯(cuò)誤用法setTimeout(function() {module.exports={ a:"hello"};? },0);});
在 y.js 里有調(diào)用到上面的 x.js:
//y.jsdefine(function(require,exports,module) {varx=require('./x');//無(wú)法立刻得到模塊 x 的屬性 aconsole.log(x.a);//undefined});
三慕趴、seajs使用定義好的模塊
1痪蝇、引入seajs
在文件夾中放入seajs,相關(guān)的html頁(yè)面引入
<script type="text/javascript" src="yourfile/js/sea.js" ></script>
2冕房、seajs經(jīng)常使用的api有use躏啰,config
seajs.use
seajs.use主要用于載入入口模塊。入口模塊相當(dāng)于C語(yǔ)言的main函數(shù)耙册,同時(shí)也是整個(gè)模塊依賴樹的根给僵。seajs.use
的用法如下:
//第一模式
seajs.use('./a');
//回調(diào)模式
seajs.use('./a',function(a){? ? a.run();})
//多模塊模式
seajs.use(['./a','./b'],function(a,b){??
? a.run();? ?
? b.run();
})
seajs.config({
????base:'path',
alias:{
? ? 'app':'path/app/'
},
charset:'utf-8',
timeout:20000,
debug:false})
base表示基址路徑
alias可以對(duì)較長(zhǎng)的常用路徑設(shè)置縮寫
charset表示下載js時(shí)script標(biāo)簽的charset屬性。
timeout表示下載文件的最大時(shí)長(zhǎng)详拙,以毫秒為單位帝际。