AMD規範學習筆記

來源:互聯網
上載者:User

標籤:style   blog   http   java   使用   os   檔案   io   

背景

NodeJS的一套比較簡潔 Moudles 規範, 使得在伺服器端的模組化變得更加簡單。很長一段時間,很多公司或者項目都有自己的一套模組化機制, 卻未能形成一套統一的標準, NodeJS的Moudles規範如果運用在瀏覽器端會存在一些問題,如

  1. 伺服器端JS模組檔案就在本地,瀏覽器端則需要通過網路請求
  2. 伺服器端可以很容易的實現同步或非同步請求模組,瀏覽器端代價會比較大

採用XHR的方式實現同步請求模組,存在明顯的跨域缺陷,而使用script的方式,預設是非同步。 在這樣的背景下, CommonJS的Modules/Wrappings、AMD、CMD等規範應時而生。

Modules/Wrappings 規範的約定如下,更多請參考:http://wiki.commonjs.org/wiki/Modules/Wrappings

  1. 使用modules.declare定義模組
  2. declare 只接受一個參數,類型可以是函數也可以是object,參數又稱為module factory
  3. 如果factory為function,三個參數分別為require、exports、module,factory使用傳回值或exports匯出模組API
  4. factory如果是物件類型,則將該對象作為模組輸出

A basic wrapped module:

module.declare(function(require, exports, module){    exports.foo = "bar";});
AMD 規範

AMD:全稱為非同步模組定義, 是專門為瀏覽器中JavaScript環境設計的規範. 規範本身非常簡單, 概括如下:

define(id?, dependencies?, factory);

  id: 模組名

  dependencies: 依賴的模組,如果預設,預設為 ["require", "exports", "module"]

  factory: 模組工廠,通過排列組合這種模組定義能滿足很多情境的需求

AMD在定義自己的Module規範的同時,也簡單相容了CommonJS的Modules/Wrappings。

匿名模組與具名模組
define(["beta"], function (beta) {    exports.verb = function() {           return beta.verb();       }}); define(‘alpha‘, ["beta"], function (beta) {    exports.verb = function() {           return beta.verb();       }});

匿名模組也帶來一些好處,如減少維護成本,使得模組的原始碼與它的標識分離。從而實現在不改變模組代碼的情況下移動源碼檔案的位置等。

Simplified CommonJS wrapping
define(function(require, exports, module){    var query = require("query");    var on = require("on");    ...});

AMD模組載入器將會掃描該工廠函數的require調用,並自動的在運行該Factory 方法之前載入他們, 也是和CMD規範的重要區別, 很多人在討論到AMD、CMD上都會探討這個問題,有許多爭議, 不過這點也正是體現了AMD規範的核心:模組依賴必須在真正執行具體的factory方法前解決。

RequireJS是目前最流行的AMD載入器,從代碼中可以看出,為了支援CommonJS Wrapping, define會解析工廠函數的FunctionBody,去掉注釋,並將require的模組匹配出來, 加到dependencies數組中。

var commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,    cjsRequireRegExp = /[^.]\s*require\s*\(\s*["‘]([^‘"\s]+)["‘]\s*\)/g; if (!deps && isFunction(callback)) {    deps = [];       if (callback.length) {               callback                       .toString()                       .replace(commentRegExp, ‘‘)            .replace(cjsRequireRegExp, function (match, dep) {                               deps.push(dep);            });         deps = (callback.length === 1 ? [‘require‘] : [‘require‘, ‘exports‘, ‘module‘]).concat(deps);     }}

由於實際項目中的FunctionBody情況比較複雜,cjsRequireRegExp,這個匹配規則不是很強大,如果在實際項目中發現require有問題的地方, 可以將FunctionBody手動匹配一下這個Regex, 看是否有問題。

exports有什麼好處?

1、相對使用return輸出對象, 由於js語言特性決定,代碼依次執行, 當模板存在循環相依性關係時,這種export匯出就會特別有用。

2、相對於命名空間匯出API,它的好處在於它不會影響全域空間, 而且匯出的API所屬的對象名稱不會和模組代碼強耦合。 這也是YUI的模組API匯出方式採用命名空間的一點局限。

資料或者獨立API模組

對於一些僅僅提供資料或者獨立方法的模組,factory格式變為obj就可以了, 如:

define({    camelCase: function(x) {      return string.camelCase(‘abc ABC‘);    }});
AMD Plugin Dependency

一個外掛程式依賴應該被描述為如下格式:

[Plugin Module ID]![resource ID]

目前流行的RequireJS、curl、Dojo等支援AMD的載入器都支援外掛程式, 如載入各種格式的資料,在domReady 完成後在執行操作等。由於“!”被外掛程式文法佔用,所以在一般資源請求中,請不要使用帶有“!”的URL。 完整的外掛程式清單可以參考http://requirejs.org/docs/download.html#plugins

下面是兩個RequireJS使用插入的例子:

define([    ‘backbone‘,    ‘text!templates.html‘], function( Backbone, template ){   // ...}); require([‘domReady!‘], function (doc) {    //This function is called once the DOM is ready,    //notice the value for ‘domReady!‘ is the current    //document.});
如果讓自己的模組支援AMD規範

jquery是如何做的?

if ( typeof define === "function" && define.amd && define.amd.jQuery ) {    define("jquery", [], function () { return jQuery; } );}

需要在載入中設定:

define.amd = {    jQuery: true}; 
小結

AMD僅僅提供了模組定義的規則,在實際項目使用中還需要考慮一些模組合并、打包方案等。

目前,實現AMD規範的庫有RequireJS 、curl 、Dojo 、bdLoad 、JSLocalnet 、Nodules等,也有很多庫支援AMD規範,即將自己作為一個模組存在,如MooTools 、jQuery 、qwery 、bonzo、firebug等。 在前端模組化發展如此快的今天,未來應該會有很多庫或者模組會支援作為滿足AMD、CMD or CommonJS Module規範的模組存在。

隨著模組化的發展,高品質的模組會越來越多,為了讓大家有統一的規則來使用模組, 模組正常化就顯得格外重要。 而不管是哪一種模組規範,未來在瀏覽器端前端是否也可以像Nodejs一樣靈活的去使用滿足相同規範,甚至各種不同規範的優秀模組, 這樣就不用將代碼局限同一種架構中, 或許只是自己瞎想。

 

參考:

http://wiki.commonjs.org/wiki/Modules/1.1.1#Module_Identifiers

https://github.com/amdjs/amdjs-api

https://github.com/requirejs/example-multipage

http://requirejs.org/docs/whyamd.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.