摘要:它就是一套兼容方案,目前兼容的有以及原生支持。返回值問題在第一次使用時,。具體是什么意義呢的返回值,其實就是插件提供的對外接口,而實際上,就是一個對象。而在環境下,只需要將這個返回值賦予即可完成該模塊的接口。
有更新,請到github上看源碼
什么是OMD在node.js流行起來之前,javascript的開發方式都是函數式的順序依賴關系,直到node火起來。CommonJS其實首先提供了一個豐富的可擴展的庫,在此基礎上提供可應用的API,在這些API的基礎上,逐漸形成一套規范,使得javascript的開發在這些規范的基礎上進行。它的重要特征就是運行開發者模塊化的開發javascript,提供一個模塊,這個模塊對外提供接口,有一個入口去調動所有的模塊協同完成不同的功能。node就是在此規范上建立起來的服務端框架。
node可以被認為是應用程序開發的一個案例,它是運行在服務器上的javascript。而是否可以在瀏覽器上面也遵循CommonJS規范呢?為了達到這個目的,requirejs火起來,與它對應的是AMD規范。實際上,AMD規范是CommonJS的一個兼容方案,requirejs希望建立一個既滿足應用程序,又滿足瀏覽器運行的規范。AMD也逐漸被開發者接受,國外很多javascript發布產品,基本上都遵循或支持amd規范。
seajs是專注于瀏覽器的模塊化javascript開發框架,和前兩者不同的是,它只專注于瀏覽器端,而且更優雅靈活,它所遵循的是CMD規范,其創始人為中國的前端大牛玉伯。自此,三家分立,各有裨益,javascript的模塊化開發規范已經被創立完畢,以后就將其逐漸完善,并實現更多的應用。
在此基礎上,有人試圖實現兼容。也就是自己的代碼既能在node上運行,也能在符合amd規范的代碼環境中運行。于是產生了umd,其實umd并不算規范,而只能算一種兼容方案,它可以兼容CommonJS和AMD。但國內更多的其實是使用seajs,包括淘寶、騰訊的部分產品,都是使用seajs框架,而react等的跑火,有理由相信,未來的前端開發一定是模塊化趨勢的。
就目前而言,為了能兼容commonjs amd cmd以及原生的javascript,我結合了前人的經驗,發布了omd,它也不是什么規范,只是一套兼容方案罷了。
omd的目的,就是希望開發javascript按照這個規則來完成代碼,就能使它在模塊化開發環境下能跑,在普通的javascript或jquery代碼中也能跑。它就是一套兼容方案,目前兼容的有module.exports、amd、cmd以及原生支持。
OMD的源碼首先,我需要將源碼放出來,所有的讀者可以先簡單的看下它的內容,大致了解它的運行規則。在github上follow這個項目,隨時了解最新的一些變化。
OMD原理詳解在《javascript立即執行某個函數:插件中function(){}()再思考》一文中,我詳細闡述了!function(fun){}(function($){});,因此這里就不詳細闡述了。
兼容amd和cmd
if(typeof define == "function" && (define.amd != undefined || define.cmd != undefined) { define(function() { return fun(); }); }
上面這段代碼,僅在amd或cmd規范下使用時才執行define。我們這里把范圍縮小到requirejs和sea.js。對于requirejs而言,define和define.amd是可見的,因此執行define(function(){});,同樣的道理,seajs也會執行。但是作為兩種不同的規范,為何可以以相同的代碼返回呢?
在requirejs中,一個模塊可以如此去定義:
define({});
define(factory);
define(id,dependencies,factor);
define(dependencies,factor)
在seajs中也差不多,但是也有不同之處:
define({});
define(factory);
define(id,dependencies,factory);
define(id,factory);
前面三種都是一樣的,但是細節上也有所不同,第一種以對象的方式定義并不能解決我們插件中接口傳遞的目的,因此不考慮。剩下的就只有兩種相同的形式,但是就像前文說到的一樣,OMD是為了實現兼容,也就是說它必須作為框架被應用,框架的基礎代碼具有穩定性,不能讓用戶改來改去,否則也就失去了規范的意義。而在剩下的兩種中,define(id,dependencies,factory)的前兩個變量,都需要自己去定義,因此,也被排除。最終也就只有define(factory)這種形式被我們采用。
define(function(require,exports,module){ var a = require("a"); });
這種代碼形式在require.js和sea.js中都可以使用,可是在sea.js中,可以使用exports.xxx = function(){}來提供接口,可是在require.js中,不得不采用return的形式,幸好,在sea.js中,return也是有效的。所以,最終,我們選擇了return的形式向外提供接口:
define(function(){ return { fun1 : function(a,b) {}, fun2 : function(c,d) {} }; // return的結果為一個對象 });
在sea.js或require.js中:
define(function(){ var $omd = require("omd"); var fun1 = $omd.fun1(12,34); });
這樣,在omd.js中寫的插件所提供的模塊接口,就可以被使用了。
兼容comomjs
當define沒有被定義的時候,說明跟sea.js和require.js沒有任何關系了,這個時候,我們要檢查是否支持node.js。
如果是在node.js環境下運行,那么module和exports是一個由核心庫提供的全局變量。因此,只需要將插件提供的接口賦值給module.exports,就完成了當前文件(模塊)所提供的接口了。
兼容原生的javascript
當以上情況都不滿足的情況下,實際上,你所提供的接口,就是一個函數。你提供了一個fun1的接口,你就可以在其他javascript代碼中執行fun1()函數。
全局變量$和局部變量$把$作為變量名,最大的好處是兼容jquery和zepto。在第一個function(factory){}中,我兩次使用到了factory($),在這里,$沒有被事先聲明過,因此用了一個if(typeof $ === "undefined")做判斷。但是如果當前環境下已經加載了jquery或zepto,$就是一個全局變量,實際上它是window.$。因此,在執行factory($)時,實際上是把$作為參數傳遞給了factory()。
而在前面那篇關于立即執行函數的文章中我已經講過了,在這里的factory()實際上就是第二個我們要真正用來寫插件代碼的function($){},要理解這一點,你必須讀懂上面那篇文章。
在factory($)中,$如果代表jquery或zepto,那么它實際上是一個全局變量。而到了function($),$實際上成為函數的參數,成為一個局部變量。在function($){}中,雖然你可以使用$("#div1")進行選擇,但你要知道,這里的$并非全局變量window.$,而是傳遞而來的,是它的引用。下文還會提到,要使用 var jQuery = $; 這樣詭異的代碼來處理某些情況。
factory($)返回值問題在第一次使用factory($)時,return factory($)。第二次時,ex = factory($)。從值的返回角度講,factory($)必然存在一個return。具體是什么意義呢?
factory($)的返回值,其實就是插件提供的對外接口,而實際上,就是一個對象Object。我們可以在第一次return factory($);的時候,也先執行一次賦值操作:
define(function(){ var ex = factory($); return ex; });
前面已經講過了,amd和cmd在define的function中return,實際上是模塊對外提供接口的一種方式,而這種方式,必須保證以對象的形式返回。因此,在插件代碼中,你可以看到,我首先定義的是一個ex = {},然后執行return ex;從而對外提供了接口。
而在node.js環境下,只需要將這個ex返回值賦予exports即可完成該模塊的接口。在原生的JavaScript環境下,沒有接口這種概念,對外提供的,則是函數或對象屬性,將它賦予window對象,就相當于提供了一個全局函數或全局變量。
OMD開發規則利用omd開發兼容各個規范的插件(模塊)時,只需要在// 真正的插件代碼都在這里這句注釋后面撰寫插件代碼即可,無需像其他教程所示一樣,寫一個(function($){}(jQuery)),直接寫插件內容即可。如果無需對外提供接口,則寫完插件代碼就可以完成開發。
關于var jQuery = $
在插件代碼中,一些插件并沒有使用$,而是使用jQuery。但是前文已經提到了,在這個函數內部,jQuery是未定義的,$是傳遞過來的變量,因此,將$賦值給jQuery,則讓jQuery重新有效。
如果需要對外提供接口,則在// 接口開始后面使用對象屬性的方式,將接口賦值給ex。注意一點,ex返回后,你不可以通過接口改變插件內部的變量,這個接口是對外接口。
利用OMD開發的步驟1.在開始開發插件之前,將omd.js的代碼框架拷貝到你的項目(插件)文件中;
2.在注釋中對應的位置開始撰寫你的腳步代碼
3.在注釋中指出接口輸出的位置處,通過ex.fun = function(){}的方式返回接口
4.完成代碼寫作之后,利用JavaScript壓縮工具,凈化和壓縮你的Javascript代碼
OMD使用要點和sea.js不同,require.js的所有模塊都是異步加載,這意味著你不能按照以往的方式,通過先加載哪個模塊,然后加載另外一個模塊來確定它們的依賴關系。不幸的是,所有的jquery插件都要依賴jquery庫。因此,在require中需要解決好這個依賴問題。依賴的用法只有在define的參數中,前面已經提到了define的幾種用法,我們來看下具體的實現方法:
define(["jquery"],function($){ require(["plugin.omd.js"],function($plugin){ $("#test").plugin(); $plugin.p("#test"); }); });
上面的代碼中,define(["jquery"])首先確定了這個模塊依賴于jquery,并將其返回接口以$作為變量。在這個基礎上,再去require(omd.js),則可以讓omd.js中的對jQuery的依賴可以實現,omd.js中才可以正常使用jquery。
不過,從require.js的設計上,模塊之間都是異步加載的,如果按照上述方法解決依賴問題,性能上比sea.js要差很多。
我已經將這個代碼放到github上,里面有demo,你可以看下plugin.js和main.js,來看看具體的用法。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78597.html
摘要:模塊標準有三個全局變量和。模塊中有兩種方式提供對外的接口,一種是,一種是使用進行返回。規范中,函數同樣有一個公有屬性。由于和都可以使用來定義對外接口,故可以合并成一句代碼。 模塊標準 CommonJS CommonJS 有三個全局變量 module、exports 和 require。但是由于 AMD 也有 require 這個全局變量,故不使用這個變量來進行檢測。 如果想要對外提供接...
摘要:所有依賴這個模塊的語句,都定義在一個回調函數中,等到所有依賴加載完成之后前置依賴,這個回調函數才會運行。如果將前面的代碼改寫成形式,就是下面這樣定義了一個文件,該文件依賴模塊,當模塊加載完畢之后執行回調函數,這里并沒有暴露任何變量。 模塊化是我們日常開發都要用到的基本技能,使用簡單且方便,但是很少人能說出來但是的原因及發展過程。現在通過對比不同時期的js的發展,將JavaScript模...
摘要:模塊化規范有的模塊系統。規范是服務器端模塊的規范,由推廣使用。對于依賴的模塊,是提前執行,是延遲執行。瀏覽器廠商和都宣布要原生支持該規范。它將逐漸取代和規范,成為瀏覽器和服務器通用的模塊解決方案。 本文由云+社區發表 模塊化是指把一個復雜的系統分解到一個一個的模塊。 模塊化開發的優點: (1)代碼復用,讓我們更方便地進行代碼管理、同時也便于后面代碼的修改和維護。 (2)一個單獨的文件就...
摘要:所有依賴這個模塊的語句,都定義在一個回調函數中,等到加載完成之后,這個回調函數才會運行。也采用語句加載模塊,但是不同于,它要求兩個參數第一個參數,是一個數組,里面的成員就是要加載的模塊第二個參數,則是加載成功之后的回調函數。 本篇文章來自對文章《js模塊化編程之徹底弄懂CommonJS和AMD/CMD!》的總結,大部分摘自文章原話,本人只是為了學習方便做的筆記,之后有新的體會會及時補充...
摘要:模塊中定義的全局變量只作用于該文件內部,不污染其他模塊。由純編寫的部分稱為內建模塊,例等模塊部分使用編寫。兼容多種模塊規范檢測是否為或者檢測是否為或環境定義為普通模塊將模塊執行結果掛載在對象下 1.為什么要CommonJS規范 javascript存在的缺點 沒有模塊系統 標準庫比較少 沒有標準接口 缺乏包管理系統 CommonJS規范的提出,彌補了javascript沒有標準的缺...
閱讀 819·2021-10-25 09:48
閱讀 611·2021-08-23 09:45
閱讀 2496·2019-08-30 15:53
閱讀 1758·2019-08-30 12:45
閱讀 586·2019-08-29 17:21
閱讀 3406·2019-08-27 10:56
閱讀 2547·2019-08-26 13:48
閱讀 691·2019-08-26 12:24