本文轉自張洋,由於SeaJS更新版本很快,因此原文中不少地方不太適用,在這裏發佈一個更新版。javascript
SeaJS是一個遵循CommonJS規範的JavaScript模塊加載框架,能夠實現JavaScript的模塊化開發及加載機制。使用SeaJS能夠提升JavaScript代碼的可讀性和清晰度,解決目前JavaScript編程中廣泛存在的依賴關係混亂和代碼糾纏等問題,方便代碼的編寫和維護。
SeaJS自己遵循KISS(Keep it Simple,Stupid)理念進行開發,後續的幾個版本更新也都是吵着這個方向邁進。css
下載及安裝在這裏不贅述了,不瞭解的請查詢官網。html
SeaJS中使用define
函數定義一個模塊。define能夠接收三個參數:java
/** * Defines a module. * @param {string=} id The module id. * @param {Array.|string=} deps The module dependencies. * @param {function()|Object} factory The module factory function. */ fn.define = function(id, deps, factory) { //code of function… }
define能夠接收的參數分別是模塊ID,依賴模塊數組及工廠函數。jquery
可是,包括SeaJS官網示例在內幾乎全部用到define的地方都只傳遞一個工廠函數進去,相似於以下代碼:編程
define(function(require,exports,module){ //code of the module })
我的建議遵循SeaJS官方示例的標準,用一個參數的define定義模塊。那麼id和deps會怎麼處理呢?json
id是一個模塊的標識字符串,define只有一個參數時,id會被默認賦值爲此js文件的絕對路徑。如example.com下的a.js文件中使用define定義模塊,則這個模塊的ID會賦值爲 http://example.com/a.js ,沒有特別的必要建議不要傳入id。deps通常也不須要傳入,須要用到的模塊用require加載便可。數組
工廠函數是模塊的主體和重點。它的三個參數分別是:app
module是一個對象,存儲了模塊的元信息,具體以下:框架
第一種是基於exports的模式:
define(function(require,exports,module){ var a=require('a'); var b=require('b'); //引入模塊 var data1=1; //私有數據 var fun1=function(){//私有方法 return a.run(data1); } exports.data2=2; //公有數據 exports.fun2=function(){ return 'hello'; } })
上面是一種比較「正宗」的模塊定義模式。除了講公共數據和方法附加在exports上,也能夠直接返回一個對象表示模塊,以下面的代碼與上面的代碼功能相同:
define(function(require){ var a=require('a'); var b=require('b'); //引入模塊 var data1=1; var fun1=function(){ return a.run(data1); } return{ data2:2, fun2:function(){ return 'hello'; } } })
若是模塊定義沒有其餘代碼,只返回一個對象,還能夠有以下簡化寫法:
define({ data2:2, fun2:function(){ return 'hello'; } })
第三種寫法對於定義純JSON數據的模塊很是合適。
根據應用場景的不一樣,SeaJS提供了三個載入模塊的API,分別是:seajs.use,require和require.async。
seajs.use主要用於載入入口模塊。入口模塊至關於C語言的main函數,同時也是整個模塊依賴樹的根。seajs.use
的用法以下:
//第一模式 seajs.use('./a'); //回調模式 seajs.use('./a',function(a){ a.run(); }) //多模塊模式 seajs.use(['./a','./b'],function(a,b){ a.run(); b.run(); })
其中多模塊的用法和KISSY中的模塊加載方法相似,不虧是一我的寫的啊!
通常seajs.use只用在頁面載入入口模塊,SeaJS會順着入口模塊解析全部依賴模塊並將它們加載。若是入口模塊只有一個,也能夠經過給引入seajs的script標籤加入「data-main」屬性來省略seajs.use,例如一下寫法:
<!DOCTYPE HTML> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>TinyApp</title> </head> <body> <p class="content"></p> <script src="./sea.js" data-main="./init"></script> </body> </html>
require是seajs主要的模塊加載方法,當在一個模塊中須要用到其餘模塊時通常用require加載:
var m=require('./a');
上文說過seajs會在html頁面打開時經過靜態分析一次性記載全部須要的js文件,若是想要某個js文件在用時才加載,可使用require.async。
這樣只有在用到這個模塊時,對應的js文件纔會被下載,也就實現了JavaScript代碼的按需加載。
seajs提供了一個seaj.configd的方法能夠設置全局配置,接收一個表示全局配置的配置對象,具體方法以下:
seajs.config({ base:'path', alias:{ 'app':'path/app/' }, charset:'utf-8', timeout:20000, debug:false })
其中,
timeout表示下載文件的最大時長,以毫秒爲單位。
要將現有的JS庫與seajs一塊兒使用,只需根據seajs的模塊定義規則對現有庫進行一個封裝。例如,下面是對jQuery的封裝方法:
define(function(){ /* 此處爲jquery源碼 */ })
一個完整的例子:
上文說了那麼多,知識點比較分散,因此最後我打算用一個完整的SeaJS例子把這些知識點串起來,方便朋友們概括回顧。這個例子包含以下文件:
html:
<!DOCTYPE HTML> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="content"> <p class="author"></p> <p class="blog"><a href="#">Blog</a></p> </div> <script src="sea.js"></script> <script> seajs.use('init'); </script> </body> </html>
javascript:
//init.js define(function(require, exports, module) { var $ = require('./jquery'); var data = require('./data'); var css = require('./style.css'); $('.author').html(data.author); $('.blog').attr('href', data.blog); }); //data.js define({ author: 'ZhangYang', blog: 'http://blog.codinglabs.org' });
css:
.author{color:red;font-size:10pt;} .blog{font-size:10pt;}
請注意:
1.請講jquery.js源碼文件包含在seajs模塊加載代碼中;
2.在Sea.js < 2.3.0版本以前是能夠加載css文件的,新版本中此功能移除,爲了兼容考慮,加載css功能將做爲一個插件存在。
使用方法