一、什么是模塊化?
模塊化是指解決一個復雜的問題時自頂向下把系統划分成若干模塊的過程,有多種屬性,分別反映其內部特性。
二、為什么要模塊化(模塊化的好處)?
1.更好地分離
如果要加載多個就得就得放置多個script標簽,如果是加載模塊的話,如seaJS,就只需加載一個sea.js即可,這樣對於HTML和JavaScript分離很有好處。
2.更好的代碼組織方式
如果單個文件越來越大,維護起來問題出問題的幾率也會越來越大,一個人開發還好,如果是多人開發,不同的代碼風格,超多的業務邏輯混雜在一起,不要說維護了,光想想就蛋疼。模塊化的開發,一個文件就是一個模塊,控制了文件的粒度,每個模塊可以專注於一個功能,在多人開發時,各自管好自己的模塊就行。
3.按需加載
還是以單個文件來說,當文件大到一定程度,性能問題也隨之而來。合並文件是能減少請求,性能也會有所提升,但是當文件大到一定的體積時,此時的下載時間可能並不會比多個小文件的下載時間短,此時就需要權衡請求數和文件體積的關系了。
4.避免命名沖突
JavaScript本身是沒有命名空間的,為了避免命名沖突,經常會使用對象或閉包的辦法來避免。用對象僅僅是降低了沖突的概率而已,那經常使用的jQuery開發來說,無論是往$上擴張還是在$.fn上擴展,開發的人多了難免會起沖突。或者用自定義對象,搞個好幾層,不光是寫起來難記,這樣的調用也會在性能上打折扣的。模塊化就能很好的解決這個問題,在該模塊內的任何形式的命名都不會再和其他模塊有沖突。
5.更好的依賴處理
傳統的開發模式,如果B文件要依賴A文件,那么必須在B文件前面用script標簽先加載好A文件。如果有一天,B文件不再需要依賴A文件,或者需要增加依賴文件C,那么又得在B文件前面用script標簽加載C文件。如果這個B文件被N個頁面在調用,而且頁面還跨業務站點,那么改起來簡直就是噩夢。如果是使用模塊化,只需要在模塊內部申明好依賴的就行,增加刪除都直接修改模塊即可,在調用的時候也不用管該模塊依賴了哪些其他模塊。
三、模塊化規范
1.commonJS:通用的模塊規范(同步);
2.AMD:異步模塊定義規范(預加載);
3.CMD:通用模塊定義規范(延遲加載)。
四、模塊化框架
1.requireJS(支持AMD規范的模塊化框架)
實例:
**主頁面:** <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>requireJS測試</title> <link rel="stylesheet" href="./css/bootstrap.min.css" /> <script src="./js/require.js" data-main="./js/main"></script> </head> <body> <h1>首頁</h1> <div> <input type="button" value="顯示所有"/> <input type="button" value="增加"/> <input type="button" value="修改"/> <input type="button" value="刪除"/> </div> <div class="modal fade" id="myModal"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> <p>One fine body…</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-primary">Save changes</button> </div> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal --> </body> </html> data-main屬性的作用是,指定網頁程序的主模塊。在上例中,就是js目錄下面的main.js,這個文件會第一個被require.js加載。由於require.js默認的文件后綴名是js,所以可以把main.js簡寫成main。 **編寫主配置文件:** //主入口配置 require.config({ paths:{ student:"./student", jquery:"./jquery-1.9.1.min", bootsrap:"./bootstrap.min" } }); //主入口方法(預加載student模塊和jQuery模塊) require(["student","jquery"],function(stu,$){ console.log($("h1").html()); $("input:button:eq(0)").click(stu.showAll); $("input:button:eq(1)").click(stu.add); $("input:button:eq(2)").click(stu.update); $("input:button:eq(3)").click(stu.del); }); **編寫student模塊:** define(["jquery","bootstrap"],function($){ console.log("加載student模塊"); $("#myModal").modal(); function showAll(){ console.log("執行showAll"); } function add(){ console.log("執行add"); } function update(){ console.log("執行update"); } function del(){ console.log("執行del"); } //暴露student模塊里的函數 return{ "showAll":showAll, "add":add, "update":update, "del":del } });
2.seaJS(支持CMD規范的模塊化框架)
實例:
**主頁面:** <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>首頁</title> <link rel="stylesheet" href="./css/bootstrap.min.css" /> <script src="js/sea.js"></script> </head> <body> <h1>首頁</h1> <div> <input type="button" value="顯示所有"/> <input type="button" value="增加"/> <input type="button" value="修改"/> <input type="button" value="刪除"/> </div> <div class="modal fade" id="myModal"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> <p>One fine body…</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-primary">Save changes</button> </div> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal --> </body> <script> //seaJS配置 seajs.config({ base:"../seaJS", alias:{ main:"js/main", student:"js/student", jquery:"js/jquery-1.9.1.min", bootstrap:"js/bootstrap.min" } }); //加載主模塊 seajs.use("main"); </script> </html> **編寫main模塊:** define(function(require,exports,module){ var stu = require("student"); stu.showAll(); stu.add(); stu.update(); stu.del(); var $ = require("jquery"); $("input:button:eq(0)").click(stu.showAll); console.log($("h1")); }); **編寫student模塊:** define(function(require,exports,module){ console.log("加載student模塊"); var $ = require("jquery"); require("bootstrap")($); function showAll(){ console.log("執行showAll"); $("#myModal").modal(); } function add(){ console.log("執行add"); } function update(){ console.log("執行update"); } function del(){ console.log("執行del"); } //暴露student模塊中的函數,方法一 // exports.showAll = showAll; // exports.add = add; // exports.update = update; // exports.del = del; //暴露student模塊中的函數,方法二 module.exports = { "showAll":showAll, "add":add, "update":update, "del":del }; //暴露student模塊中的函數,方法三 // return { // "showAll":showAll, // "add":add, // "update":update, // "del":del // } });
注意:seaJS導入第三方js模塊是需要修改第三方JS的源碼,例如:
seaJS加載jQuery模塊,需要修改jQuery.js原有代碼,修改如下:
define(function(){
jQuery.js原有代碼
return $.noConflict();
});
seaJS加載boostrap模塊,同樣需要修改boostrap.js原有代碼,修改如下:
define(function(){
return function($){
boostrap.js原有代碼
}
});