轉: seajs手冊與文檔之--模塊定義


模塊定義

在 SeaJS 中,全部 JavaScript 文件都應該用模塊的形式來書寫,而且一個文件只包含一個模塊。html

define

使用全局函數 define 來定義模塊:前端

define(id?, dependencies?, factory);

id

當前模塊的惟一標識。該參數可選。若是沒有指定,默認爲模塊所在文件的訪問路徑。若是指定的話, 必須是頂級或絕對標識(不能是相對標識)。~~通常由優化工具生成node

dependencies

當前模塊所依賴的模塊,是一個由模塊標識組成的數組。該參數可選。若是沒有指定,模塊加載器會從 factory.toString() 中解析出該數組。~~~factory.toString()中用正則匹配require(..),提取依賴模塊,因此通常不用傳入dependenciesgit

** 注意:強烈推薦不要設定 iddependencies 參數。 在開發階段,模塊加載器會自動獲取這兩個參數。部署上線時,則能夠經過優化工具來提取這兩個參數。github

factory

模塊的工廠函數。模塊初始化時,會調用且僅調用一次該工廠函數。factory 能夠是函數, 也能夠是對象、字符串等任意值,這時 module.exports 會直接設置爲 factory 值。算法

factory 函數在調用時,會始終傳入三個參數: requireexportsmodule, 這三個參數在全部模塊代碼裏可用。 ~~~factory參數能夠爲字符串?json

define(function(require, exports, module) {

  // The module code goes here
  
});

exports

exports 用來向外提供模塊的 API.  ~~~注意 module.exports 和 exports指向同一對象, exports不能在模塊定義代碼中被重寫 如 exports = { foo:function(){..}, bar:200 }數組

define(function(require, exports) {
  // snip...
  exports.foo = 'bar';
  exports.doSomething = function() {};
});

除了給 exports 對象增長成員,還可使用 return 直接向外提供 API.app

define(function(require, exports) {
  // snip...
  return {
    foo: 'bar',
    doSomething: function() {};
  };
});

若是 return 語句是模塊中的惟一代碼,可簡化爲:~~~直接傳json到define(json)中異步

define({
  foo: 'bar',
  doSomething: function() {};
});

上面這種格式特別適合定義 JSON 數據。

** 注意:下面這種寫法是錯誤的!

define(function(require, exports) {
  // snip...
  exports = { // 錯誤!  exports 和 module.exports 無關聯了,只是對象字面量而已
    foo: 'bar',
    doSomething: function() {};
  };
});

模塊加載器不能獲取到新賦給 exports 變量的值。 請使用 returnmodule.exports

require

require 函數用來訪問其餘模塊提供的 API. ~~~用require函數加載依賴模塊 require(moduleID)

define(function(require) {
  var a = require('./a');
  a.doSomething();
});

它接受 模塊標識 做爲惟一參數。

請牢記,爲了使靜態分析能成功獲取到模塊依賴信息,在書寫模塊時,須要遵循一些簡單的 規則

require.async

該方法可用來異步加載模塊,並在加載完成後執行回調函數。

define(function(require, exports, module) {
  // 加載一個模塊
  require.async('./b', function(b) {
    b.doSomething();
  });
  
  // 加載多個模塊
  require.async(['./c', './d'], function(c, d) {
    // do something
  });
});

require.resolve

使用 require() 的內部機制來解析並返回模塊路徑。該函數不會加載模塊,只返回解析後的路徑。

require.load

該方法可用來異步加載腳本,並在加載完成後,執行指定的回調函數。開發插件時, 能夠經過覆蓋該方法來實現自定義的資源加載。

require.constructor

有時候,咱們須要給全部 require 參數對象添加一些公用屬性或方法。這時, 使用 require.constructor 來實現會很是方便。

module

module 參數存儲模塊的元信息。擁有如下成員:

module.id

當前模塊的惟一標識。 require(module.id) 必然返回此模塊的 exports

define(function(require, exports, module) {
  console.log(module.id); // http://path/to/this/file.js
  console.log(require(module.id) === exports); // true
});

module.dependencies

module.dependencies 是一個數組,表示當前模塊的依賴列表。

該數組只讀:模塊加載完成後,修改該數組不會有任何效果。

module.exports

exports 對象由模塊系統建立,這不能知足開發者的全部需求, 有時候會但願 exports 是某個類的實例。 這時可用 module.exports 來實現:

define(function(require, exports, module) {
  console.log(module.exports === exports); // true
  module.exports = new SomeClass();
  console.log(module.exports === exports); // false
});

注意,對 module.exports 的賦值須要同步執行,它不能放在回調函數裏。 下面這樣是不行的:

x.js:

define(function(require, exports, module) {
  setTimeout(function() {
    module.exports = { a: "hello" };
  }, 0);
});

y.js:

define(function(require, exports, module) {
  var x = require('./x');
  console.log(x.a); // undefined
});

module.constructor

時候,咱們須要給全部 module 參數對象添加一些公用屬性或方法。在這種狀況下, 使用 module.constructor 能夠很好地知足需求。

extend.js:

define(function(require, exports, module) {
  var Module = module.constructor;

  Module.prototype.filename = function() {
    var id = this.id;
    var parts = id.split('/');
    return parts[parts.length - 1];
  };
});

a.js:

define(function(require, exports, module) {
  exports.filename = module.filename();
});


--------------------------------------------------------------------------------
SeaJS提供了模塊化的能力,前面咱們已經看到了SeaJS定義模塊、引用模塊的方法,而這裏就要用到 SeaJS加載並啓動模塊的兩種方式
a、使用data-main
爲<script src="assets/scripts/seajs/sea.js" id="seajsnode"></script>添加data-main="application/application"屬性便可:
<script src="assets/scripts/seajs/sea.js"  id="seajsnode" data-main="application/application"></script>  
//~~~~ seajs.version == 2.0 data-main可用 seajs.version=2.2.x data-main方式加載入口模塊不可用; 相似requirejs的 data-main
SeaJS會根據data-main指定的模塊來做爲整個應用的入口模塊。SeaJS找到這個模塊以後,就會加載執行這個模塊對應的文件。
那麼,SeaJS又是怎麼找到這個文件呢?也就是說,這個模塊對應的加載路徑是多少?
「算法」是: SeaJS_URL_base + data-main
如上文,該例子的SeaJS_URL_base是HelloSeaJS/assets/scripts/

那麼,加載路徑就是HelloSeaJS/assets/scripts/application/application.js(SeaJS會自動加上.js後綴)

 

b、使用seajs.use
在<script src="assets/scripts/seajs/sea.js" id="seajsnode">後面加上:
<script> seajs.use("application/application"); </script>
其實這兩種效果在這個例子中是同樣的,data-main一般用在只有一個入口的狀況,use能夠用在多個入口的狀況,具體用法,看這裏: https://github.com/seajs/seajs/issues/260

若是你對你的程序有徹底的控制權,建議使用data-main的方式,這樣整個頁面就只有一段script標籤!做爲一名前端開發人員,我不得不驚歎:乾淨、完美!

 

嗯,SeaJS已經替咱們想到了這個問題,因而咱們就採用SeaJS提供的方式來合併壓縮吧(固然你也能夠本身用別的方式壓縮)。

SeaJS在2.0以前,是採用SPM做爲壓縮合並工具的,到了2.0,改成Grunt.js,SPM變爲包管理工具,相似NPM(不知道NPM?Google一下吧)

 

自動化不只是科技帶給社會的便利,也是Grunt帶給前端的瑞士軍刀。使用Grunt,能夠很方便的定製各類任務,如壓縮、合併等。使用Grunt以前,須要安裝node環境和grunt工具,Google一下,十分鐘後回來。

……

 

Grunt最核心的就兩個部分,package.json、Gruntfile.js。

相關文章
相關標籤/搜索