為什么要使用模塊化
在以前,網(wǎng)頁功能很簡單,幾行JS就能滿足交互需求。
現(xiàn)在網(wǎng)頁變得越來越復(fù)雜,JS也變得越來越龐大,這個時候就要對JS進(jìn)行模塊化的管理,把不同功能的JS劃分為不同模塊,需要什么功能只要調(diào)用該模塊就可以。
模塊化以后,提高了代碼的復(fù)用性,同時也能更好的管理文件與文件之間的依賴。
CMD、AMD、CommonJS
編寫模塊需要遵守一些規(guī)范,大家都按照一個規(guī)范進(jìn)行模塊的編寫,這樣才能相互調(diào)用。假如每個人都按自己的規(guī)范編寫模塊,就會變得混亂,失去了模塊化的初衷。
CommonJS
Node.js的模塊系統(tǒng),就是參照CommonJS規(guī)范實現(xiàn)的
假如有這么一個Math模塊,可以這樣調(diào)用
var Math = require('Math')
Math.add(1,1)
通過require()
這個方法加載模塊,然后就可以使用該模塊的功能
而在Math這個模塊中,需要使用exports
來輸出該模塊提供的功能
exports.add = function() {
//code..
}
但是該規(guī)范在瀏覽器中有個缺陷,以上面的例子,當(dāng)我require('Math')
時,Math這個模塊是存放在服務(wù)器中的,只有當(dāng)Math模塊下載完成了,Math.add(1,1)
才會執(zhí)行,就是所謂的“同步加載”。
假設(shè)我網(wǎng)速很慢,Math模塊加載時間相當(dāng)長,瀏覽器就會進(jìn)入“假死狀態(tài)”,這顯然不是我們想要的。
這個問題在服務(wù)器端就不存在,因為服務(wù)器的模塊都存在本地,加載模塊的時間就是讀取硬盤數(shù)據(jù)的時間。
AMD
AMD(Asynchronous Module Definition),意為"異步模塊定義"。
在前端中,模塊的加載都需要采取“異步加載”,避免出現(xiàn)假死的情況,因此誕生了AMD規(guī)范
而requie.js是遵循AMD的庫之一
requie.js和CommonJS一樣,都采用require()
方法進(jìn)行模塊的加載,但是其接受不一樣的參數(shù)
require([module], callback);
[module]
為模塊名,callback為模塊加載成功后需要執(zhí)行的函數(shù),因此Math的例子可以寫為
require(['Math'],function(Math){
Math.add(1,1)
})
模塊則要按ADM規(guī)范寫
define(id?, dependencies?, factory);
id
是可選參數(shù),為該模塊名稱,不提供該參數(shù),則模塊名默認(rèn)為該腳本的名字
dependencies?
為該模塊的依賴,依賴模塊標(biāo)識的數(shù)組字面量,如果該模塊不依賴其他模塊,這可忽略該參數(shù),
如果忽略此參數(shù),它應(yīng)該默認(rèn)為["require", "exports", "module"]
factory
是工廠函數(shù),是該模塊的初始化函數(shù)或?qū)ο?br>
上面的Math模塊假設(shè)依賴了jQuery,在AMD規(guī)范中該這樣寫
define(['jquery'],function($) {
var Math = (function() {
return {
add: function() {
//code...
}
}
})()
return Math
})
CMD
CMD是Sea.js推廣的過程中產(chǎn)生的,與AMD只是語法上的區(qū)別
ADM是預(yù)先加載好所有的依賴模塊,而CMD是當(dāng)我需要這個模塊時,才進(jìn)行加載
像上面到Math模塊在CMD中這樣寫
define(function(require, exports, module){
exports.add = function() {
//code..
}
})
require
是一個方法,接受模塊標(biāo)識 作為唯一參數(shù),用來獲取其他模塊提供的接口
exports
是一個對象,用來向外提供模塊接口
module
是一個對象,上面存儲了與當(dāng)前模塊相關(guān)聯(lián)的一些屬性和方法
調(diào)用Math時
var math = require('Math')
math.add()
由于github鏈接太慢,可能會出現(xiàn)bug
本地測試功能完整!
預(yù)覽Demo
源碼