Sea.js框架構建

CMD模塊定義規範

在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
   });

factory函數的參數之require

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

require書寫規範

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");

factory函數的參數之exports

exports是一個對象,用來向外提供模塊接口。正則表達式

define(function(require, exports) {
   // 對外提供foo屬性
   exports.foo = 'bar';
   // 對外提供doSomething方法
   exports.doSomething = function(){};
});

注意:exports僅僅是module.exports的一個引用。在factory內部給exports從新賦值時,並不會改變module.exports的值。所以給exports賦值是無效的,不能用來更改模塊接口。json

factory函數的參數之module

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的賦值須要同步執行,不能放在回調函數裏。

CMD規範執行流程

模塊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 $

sea.js框架構建

sea.js的引入

在調用seajs.use以前,須要先引入sea.js文件,可直接使用script標籤同步引入:

<script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-debug.js">
</script>

seajs配置說明

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>

sea.js模塊的引入

seajs.use: public API,可在全局任何位置調用該方法
<script type="text/javascript">
 seajs.use('modules/base', function(base) {
    base.script_load('index');
  });
</script>

文件後綴的自動添加規則

Sea.js在解析模塊標識時,除非在路徑中有問號(?)或最後一個字符是井號(#),不然都會自動添加JS擴展名(.js)。若是不想
自動添加擴展名,能夠在路徑末尾加上井號(#)。

JQ插件模塊化

JQ模塊化

若是想要將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插件模塊化

若是想要將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>

案例分享

案例結構如圖: Seajs案例結構.jpg

配置sea-config

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

加載JQ插件

定義應用模塊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

相關文章
相關標籤/搜索