在Sea.js中,全部JavaScript模塊都遵循CMD(Common Module Definition)模塊定義規範。該規範明確了模塊的基本書寫 格式和基本交互規則。在CMD規範中,一個模塊就是一個文件。
代碼的書寫格式爲:define(factory);javascript
define是一個全局函數,用來定義模塊。參數factory,能夠是一個函數,也能夠是一個對象或字符串。當factory爲對象、 字符串時,表示模塊的接口就是該對象、字符串。以下: 1>.能夠定義一個JSON數據模塊:define({ "foo": "bar" }); 2>.也能夠定義一個字符串模塊:define('My name is Hm.'); 3>.當factory爲函數時,表示是模塊的構造方法。執行該構造方法,能夠獲得模塊向外提供的接口。 factory方法在執行時,默認會傳入三個參數:require、exports 和 module,以下: define(function(require, exports, module) { //code });
1.require是factory函數的第一個參數,它是一個方法,接受模塊標識做爲惟一參數,用來獲取其餘模塊提供的接口。用法以下:php
define(function(require, exports, module){ // 獲取模塊a的接口 var a = require('a'); // 調用模塊a的方法 a.doSomething(); });
2.require.async方法用來在模塊內部異步加載模塊,並在加載完成後執行指定回調。callback 參數可選。css
define(function(require, exports, module) { // 異步加載b模塊,在加載完成時,執行回調 require.async('b', function(b) { b.doSomething(); }); // 異步加載多個模塊,在加載完成時,執行回調 require.async(['c', 'd'], function(c, d) { c.doSomething(); d.doSomething(); }); });
注意:require是同步往下執行,require.async則是異步回調執行。require.async通常用來加載可延遲異步加載的模塊。html
1.模塊factory構造方法的第一個參數必須命名爲require。java
// 錯誤! define(function(req) { // code }); // 正確! define(function(require) { // code });
2.不要重命名require函數,或在任何做用域中給require從新賦值。jquery
// 錯誤! define(function(req) { // code }); // 正確! define(function(require) { // code });
3.require的參數值必須是字符串直接量。web
// 錯誤! require(myModule); // 錯誤! require("my-" + "module"); // 錯誤! require("MY-MODULE".toLowerCase()); // 正確! require("my-module");
exports是一個對象,用來向外提供模塊接口。正則表達式
define(function(require, exports) { // 對外提供foo屬性 exports.foo = 'bar'; // 對外提供doSomething方法 exports.doSomething = function(){}; });
注意:exports僅僅是module.exports的一個引用。在factory內部給exports從新賦值時,並不會改變module.exports的值。所以給exports賦值是無效的,不能用來更改模塊接口。json
module是一個對象,上面存儲了與當前模塊相關聯的一些屬性和方法。 1>.module.id:模塊的惟一標識。 2>.module.uri:根據模塊系統的路徑解析規則獲得的模塊絕對路徑。 3>.module.dependencies:是一個數組,表示當前模塊的依賴。 4>.module.exports:當前模塊對外提供的接口。
傳給factory構造方法的exports參數是module.exports對象的一個引用。只經過exports參數來提供接口,有時沒法知足開發者的全部需求。好比當模塊的接口是某個類的實例時,須要經過module.exports來實現:數組
define(function(require, exports, module) { // exports是module.exports的一個引用 console.log(module.exports === exports); // true // 從新給module.exports賦值 module.exports = new SomeClass(); // exports再也不等於module.exports console.log(module.exports === exports); // false });
注意:對module.exports的賦值須要同步執行,不能放在回調函數裏。
模塊a.js:
define(function(require,exports,modules){ var $ = require('jquery') }) 1>.經過回調函數的Function.toString函數,使用正則表達式來捕捉內部的require字段,找到require('jquery')內部依賴的 模塊jquery 2>.根據配置文件,找到jquery的js文件的實際路徑 3>.在dom中插入script標籤,載入模塊指定的js,綁定加載完成的事件,使得加載完成後將js文件綁定到require模塊指定的id (這裏就是jquery這個字符串)上 4>.回調函數內部依賴的js所有加載(暫不調用)完後,調用回調函數 5>.當回調函數調用require('jquery'),即執行綁定在'jquery'這個id上的js文件,即刻執行,並將返回值傳給var $
在調用seajs.use以前,須要先引入sea.js文件,可直接使用script標籤同步引入:
<script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-debug.js"> </script>
seajs.config支持的屬性有:
'alias' : (當模塊標識很長時,可使用alias來簡化,使用alias可讓文件的真實路徑與調用標識分開,有利於統一維護。) 'paths' : (當目錄比較深,或須要跨目錄調用模塊時,可使用paths來簡化書寫,paths配置也能夠結合alias配置一塊兒使用, 讓模塊引用很是方便。) 'vars' : (有些場景下,模塊路徑在運行時才能肯定,這時可使用vars 變量來配置,vars配置的是模塊標識中的變量值,在 模塊標識中用{key}來表示變量。) 'map' : (該配置可對模塊路徑進行映射修改,可用於路徑轉換、在線調試等。) 'preload' : (使用preload配置項,能夠在普通模塊加載前,提早加載並初始化好指定模塊。preload中的空字符串會被忽略掉。) 'debug' : (值爲true時,加載器不會刪除動態插入的script標籤。插件也能夠根據debug配置,來決策log等信息的輸出。) 'base' : (Sea.js在解析模塊路徑標識時,會基於base路徑來解析。) 'charset' : (獲取模塊文件時,<script>或<link>標籤的charset屬性。 默認是utf-8)
seajs.config經常使用配置項的配置示例:
seajs.config({ // 別名配置 alias: { 'jquery': 'libs/jquery/jquery.js', 'jquery.validate': 'libs/jquery.validate/jquery.validate.js' }, // 路徑配置 paths: { 'gallery': 'https://a.alipayobjects.com/gallery' }, // 變量配置 vars: { 'locale': 'zh-cn' }, // 映射配置 map: [ ['http://example.com/js/app/', 'http://localhost/js/app/'] ], // 預加載項 preload: [ this.JSON ? '' : 'json' ], // 調試模式 debug: true, // Sea.js的基礎路徑 base: 'http://localhost/tseajs/static/js/', // 文件編碼 charset: 'utf-8' });
seajs.config配置可直接使用script標籤同步引入:
<script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-config.js"> </script>
seajs.use: public API,可在全局任何位置調用該方法 <script type="text/javascript"> seajs.use('modules/base', function(base) { base.script_load('index'); }); </script>
文件後綴的自動添加規則
Sea.js在解析模塊標識時,除非在路徑中有問號(?)或最後一個字符是井號(#),不然都會自動添加JS擴展名(.js)。若是不想 自動添加擴展名,能夠在路徑末尾加上井號(#)。
若是想要將JQ原始文件模塊化在sea.js框架中使用,可在原始JQ文件中增長以下代碼:
if ( typeof module === "object" && module && typeof module.exports === "object" ) { module.exports = jQuery; } else { window.jQuery = window.$ = jQuery; if ( typeof define === "function" ) { define( "jquery", [], function () { return jQuery; } ); } }
以下: /*! * jQuery JavaScript Library v1.9.1 * http://jquery.com/ */ (function( window, undefined ) { // jQ code if ( typeof module === "object" && module && typeof module.exports === "object" ) { module.exports = jQuery; } else { window.jQuery = window.$ = jQuery; if ( typeof define === "function" ) { define( "jquery", [], function () { return jQuery; } ); } } })( window );
如不想模塊化JQ也能夠直接使用script標籤同步引入:
<script type="text/javascript" src="http://localhost/tseajs/static/js/libs/jquery/jquery.js"> </script>
若是想要將JQ插件模塊化在sea.js框架中使用,可按照CMD規範將JQ插件定義爲JQ插件模塊:
以下: define(function (require, exports, module) { var jQuery = require("jquery");//插件若是依賴JQ時,要先引入JQ模塊 //Plugin code return jQuery; });
如不想模塊化JQ插件也能夠直接使用script標籤同步引入:
<script type="text/javascript" src="http://localhost/tseajs/static/js/libs/jquery.validate/jquery.validate.js"> </script>
sea-config.js文件的配置以下:
seajs.config({ // 別名配置 alias: { 'jquery': 'libs/jquery/jquery.js', 'jquery.validate': 'libs/jquery.validate/jquery.validate.js' }, // 變量配置 vars: { 'locale': 'zh-cn' }, // 調試模式 debug: true, // 基礎路徑 base: 'http://localhost/tseajs/static/js/', // 文件編碼 charset: 'utf-8' });
定義主模塊base.js文件,以下:
/** *項目主模塊 */ define(function(require, exports, module) { //加載jquery, 並把$設爲全局變量 window.$ = window.jQuery = $ = require('jquery'); //定義一個全局的模塊加載函數.module爲模塊名,options爲參數 exports.script_load = function(module, options) { //使用require.async異步加載模塊。模塊須要提供一個固定的對外調用接口,這裏定義爲run。 require.async('modules/' + module, function(module) { if (typeof(module.run) === 'function') { module.run(options); } }); }; });
定義應用模塊index.js文件,以下:
define(function(require, exports, module) { var eventInit = function(){ $('#alert').click(function() { alert('test-4'); }); }; exports.run = function(){ //提供對外的調用接口run() $(function(){ alert('test-2'); alert('test-3'); }); $(alert('test-1')); eventInit() }; });
在app/index/index.html文件中使用定義的模塊:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>sea.js應用</title> </head> <body> <button id="alert">點擊我</button> </body> <script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-debug.js"></script> <script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-config.js"></script> <script type="text/javascript"> seajs.use('modules/base', function(base) {//啓動主模塊base.js base.script_load('index');//加載index.js }); </script> </html>
在瀏覽器中運行,在控制檯中查看元素,經過模塊加載器加載了jq文件,以下:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>sea.js應用</title> <script charset="utf-8" async="" src="http://localhost/tseajs/static/js/modules/base.js"></script>//加載了base.js模塊 <script charset="utf-8" async="" src="http://localhost/tseajs/static/js/libs/jquery/jquery.js"></script>//加載了jquery.js模塊 <script charset="utf-8" async="" src="http://localhost/tseajs/static/js/modules/index.js"></script>//加載了index.js模塊 </head> <body> <button id="alert">點擊我</button> <script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-debug.js"></script> <script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-config.js"></script> <script type="text/javascript"> seajs.use('modules/base', function(base) {//啓動主模塊base.js base.script_load('index');//加載index.js }); </script> </body> </html>
運行結果
運行文件後會依此彈出test-1,test-2,test-3,在點擊按鈕後會彈出test-4
定義應用模塊login.js文件,以下:
define(function(require, exports, module) { require('jquery.validate');//引入模塊化後的jq插件 var onReady = function() { $('form.login-form').validate({ debug: true, rules: { '[name=username]': { required: true }, '[name=password]': { required: true, rangelength:[3,10] } }, submitHandler: function(form) { alert("提交表單"); form.submit(); } }); }; exports.run = function() { $(onReady()); } });
在app/login/index.html文件中使用定義的模塊:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>validator</title> <style type="text/css"> //樣式定義 </style> </head> <body> <div id="form"> <form class="login-form" method="post" action=""> <input name="username" type="text" required><br /> <input name="password" type="password" required><br /> <button class="button" type="submit">登錄</button> </form> </div> <script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-debug.js"></script> <script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-config.js"></script> <script type="text/javascript"> seajs.use('modules/base', function(base) {//啓動主模塊base.js base.script_load('login');//加載login.js }); </script> </body> </html>
在瀏覽器中運行,在控制檯中查看元素,經過模塊加載器加載了jq文件以及jq插件文件,以下:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>validator</title> <style type="text/css"> //樣式定義 </style> <script charset="utf-8" async="" src="http://localhost/tseajs/static/js/modules/base.js"></script>//加載了base.js模塊 <script charset="utf-8" async="" src="http://localhost/tseajs/static/js/libs/jquery/jquery.js"></script>//加載了jquery.js模塊 <script charset="utf-8" async="" src="http://localhost/tseajs/static/js/modules/login.js"></script>//加載了login.js模塊 <script charset="utf-8" async="" src="http://localhost/tseajs/static/js/libs/jquery.validate/jquery.validate.js"></script>//加載了jquery.validate.js模塊 </head> <body> <div id="form"> <form class="login-form" method="post" action="" novalidate="novalidate"> <input name="username" type="text" required=""><br> <input name="password" type="password" required=""><br> <button class="button" type="submit">登錄</button> </form> </div> <script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-debug.js"></script> <script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-config.js"></script> <script type="text/javascript"> seajs.use('modules/base', function(base) { base.script_load('login'); }); </script> </body> </html>
運行結果
運行案例,若輸入框爲空直接點擊登錄按鈕會提示「This field is required.」;若在輸入框中輸入內容後再點擊登錄按鈕則可 正常登錄。
注意:由於jquery.validate.js插件依賴於jquery.js因此引入jquery.validate.js插件前須要先引入jquery.js,所以可在模塊化jquery.validate.js插件時,先require("jquery")便可。可參考上面JQ插件模塊化部分
Seajs 官網 http://seajs.org/docs
Seajs API文檔 http://yslove.net/seajs
SeaJS中jQuery插件模塊化及其調用方式 http://web322-szb.iteye.com/blog/1742930