成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

OMD: javascript模塊化開發(fā)兼容CommonJS, AMD, CMD 以及 原生 JS

lavor / 3173人閱讀

摘要:它就是一套兼容方案,目前兼容的有以及原生支持。返回值問題在第一次使用時,。具體是什么意義呢的返回值,其實(shí)就是插件提供的對外接口,而實(shí)際上,就是一個對象。而在環(huán)境下,只需要將這個返回值賦予即可完成該模塊的接口。

有更新,請到github上看源碼

什么是OMD

在node.js流行起來之前,javascript的開發(fā)方式都是函數(shù)式的順序依賴關(guān)系,直到node火起來。CommonJS其實(shí)首先提供了一個豐富的可擴(kuò)展的庫,在此基礎(chǔ)上提供可應(yīng)用的API,在這些API的基礎(chǔ)上,逐漸形成一套規(guī)范,使得javascript的開發(fā)在這些規(guī)范的基礎(chǔ)上進(jìn)行。它的重要特征就是運(yùn)行開發(fā)者模塊化的開發(fā)javascript,提供一個模塊,這個模塊對外提供接口,有一個入口去調(diào)動所有的模塊協(xié)同完成不同的功能。node就是在此規(guī)范上建立起來的服務(wù)端框架。

node可以被認(rèn)為是應(yīng)用程序開發(fā)的一個案例,它是運(yùn)行在服務(wù)器上的javascript。而是否可以在瀏覽器上面也遵循CommonJS規(guī)范呢?為了達(dá)到這個目的,requirejs火起來,與它對應(yīng)的是AMD規(guī)范。實(shí)際上,AMD規(guī)范是CommonJS的一個兼容方案,requirejs希望建立一個既滿足應(yīng)用程序,又滿足瀏覽器運(yùn)行的規(guī)范。AMD也逐漸被開發(fā)者接受,國外很多javascript發(fā)布產(chǎn)品,基本上都遵循或支持amd規(guī)范。

seajs是專注于瀏覽器的模塊化javascript開發(fā)框架,和前兩者不同的是,它只專注于瀏覽器端,而且更優(yōu)雅靈活,它所遵循的是CMD規(guī)范,其創(chuàng)始人為中國的前端大牛玉伯。自此,三家分立,各有裨益,javascript的模塊化開發(fā)規(guī)范已經(jīng)被創(chuàng)立完畢,以后就將其逐漸完善,并實(shí)現(xiàn)更多的應(yīng)用。

在此基礎(chǔ)上,有人試圖實(shí)現(xiàn)兼容。也就是自己的代碼既能在node上運(yùn)行,也能在符合amd規(guī)范的代碼環(huán)境中運(yùn)行。于是產(chǎn)生了umd,其實(shí)umd并不算規(guī)范,而只能算一種兼容方案,它可以兼容CommonJS和AMD。但國內(nèi)更多的其實(shí)是使用seajs,包括淘寶、騰訊的部分產(chǎn)品,都是使用seajs框架,而react等的跑火,有理由相信,未來的前端開發(fā)一定是模塊化趨勢的。

就目前而言,為了能兼容commonjs amd cmd以及原生的javascript,我結(jié)合了前人的經(jīng)驗(yàn),發(fā)布了omd,它也不是什么規(guī)范,只是一套兼容方案罷了。

omd的目的,就是希望開發(fā)javascript按照這個規(guī)則來完成代碼,就能使它在模塊化開發(fā)環(huán)境下能跑,在普通的javascript或jquery代碼中也能跑。它就是一套兼容方案,目前兼容的有module.exports、amd、cmd以及原生支持。

OMD的源碼

首先,我需要將源碼放出來,所有的讀者可以先簡單的看下它的內(nèi)容,大致了解它的運(yùn)行規(guī)則。在github上follow這個項(xiàng)目,隨時了解最新的一些變化。

OMD原理詳解

在《javascript立即執(zhí)行某個函數(shù):插件中function(){}()再思考》一文中,我詳細(xì)闡述了!function(fun){}(function($){});,因此這里就不詳細(xì)闡述了。

兼容amd和cmd

if(typeof define == "function" && (define.amd != undefined || define.cmd != undefined) {
  define(function() {
    return fun();
  });
}

上面這段代碼,僅在amd或cmd規(guī)范下使用時才執(zhí)行define。我們這里把范圍縮小到requirejs和sea.js。對于requirejs而言,define和define.amd是可見的,因此執(zhí)行define(function(){});,同樣的道理,seajs也會執(zhí)行。但是作為兩種不同的規(guī)范,為何可以以相同的代碼返回呢?

在requirejs中,一個模塊可以如此去定義:

define({});
define(factory);
define(id,dependencies,factor);
define(dependencies,factor)

在seajs中也差不多,但是也有不同之處:

define({});
define(factory);
define(id,dependencies,factory);
define(id,factory);

前面三種都是一樣的,但是細(xì)節(jié)上也有所不同,第一種以對象的方式定義并不能解決我們插件中接口傳遞的目的,因此不考慮。剩下的就只有兩種相同的形式,但是就像前文說到的一樣,OMD是為了實(shí)現(xiàn)兼容,也就是說它必須作為框架被應(yīng)用,框架的基礎(chǔ)代碼具有穩(wěn)定性,不能讓用戶改來改去,否則也就失去了規(guī)范的意義。而在剩下的兩種中,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的結(jié)果為一個對象
});

在sea.js或require.js中:

define(function(){
    var $omd = require("omd");
    var fun1 = $omd.fun1(12,34);
});

這樣,在omd.js中寫的插件所提供的模塊接口,就可以被使用了。

兼容comomjs

當(dāng)define沒有被定義的時候,說明跟sea.js和require.js沒有任何關(guān)系了,這個時候,我們要檢查是否支持node.js。

如果是在node.js環(huán)境下運(yùn)行,那么module和exports是一個由核心庫提供的全局變量。因此,只需要將插件提供的接口賦值給module.exports,就完成了當(dāng)前文件(模塊)所提供的接口了。

兼容原生的javascript

當(dāng)以上情況都不滿足的情況下,實(shí)際上,你所提供的接口,就是一個函數(shù)。你提供了一個fun1的接口,你就可以在其他javascript代碼中執(zhí)行fun1()函數(shù)。

全局變量$和局部變量$

把$作為變量名,最大的好處是兼容jquery和zepto。在第一個function(factory){}中,我兩次使用到了factory($),在這里,$沒有被事先聲明過,因此用了一個if(typeof $ === "undefined")做判斷。但是如果當(dāng)前環(huán)境下已經(jīng)加載了jquery或zepto,$就是一個全局變量,實(shí)際上它是window.$。因此,在執(zhí)行factory($)時,實(shí)際上是把$作為參數(shù)傳遞給了factory()。

而在前面那篇關(guān)于立即執(zhí)行函數(shù)的文章中我已經(jīng)講過了,在這里的factory()實(shí)際上就是第二個我們要真正用來寫插件代碼的function($){},要理解這一點(diǎn),你必須讀懂上面那篇文章。

在factory($)中,$如果代表jquery或zepto,那么它實(shí)際上是一個全局變量。而到了function($),$實(shí)際上成為函數(shù)的參數(shù),成為一個局部變量。在function($){}中,雖然你可以使用$("#div1")進(jìn)行選擇,但你要知道,這里的$并非全局變量window.$,而是傳遞而來的,是它的引用。下文還會提到,要使用 var jQuery = $; 這樣詭異的代碼來處理某些情況。

factory($)返回值問題

在第一次使用factory($)時,return factory($)。第二次時,ex = factory($)。從值的返回角度講,factory($)必然存在一個return。具體是什么意義呢?

factory($)的返回值,其實(shí)就是插件提供的對外接口,而實(shí)際上,就是一個對象Object。我們可以在第一次return factory($);的時候,也先執(zhí)行一次賦值操作:

define(function(){
    var ex = factory($);
    return ex;
});

前面已經(jīng)講過了,amd和cmd在define的function中return,實(shí)際上是模塊對外提供接口的一種方式,而這種方式,必須保證以對象的形式返回。因此,在插件代碼中,你可以看到,我首先定義的是一個ex = {},然后執(zhí)行return ex;從而對外提供了接口。

而在node.js環(huán)境下,只需要將這個ex返回值賦予exports即可完成該模塊的接口。在原生的JavaScript環(huán)境下,沒有接口這種概念,對外提供的,則是函數(shù)或?qū)ο髮傩?,將它賦予window對象,就相當(dāng)于提供了一個全局函數(shù)或全局變量。

OMD開發(fā)規(guī)則

利用omd開發(fā)兼容各個規(guī)范的插件(模塊)時,只需要在// 真正的插件代碼都在這里這句注釋后面撰寫插件代碼即可,無需像其他教程所示一樣,寫一個(function($){}(jQuery)),直接寫插件內(nèi)容即可。如果無需對外提供接口,則寫完插件代碼就可以完成開發(fā)。

關(guān)于var jQuery = $

在插件代碼中,一些插件并沒有使用$,而是使用jQuery。但是前文已經(jīng)提到了,在這個函數(shù)內(nèi)部,jQuery是未定義的,$是傳遞過來的變量,因此,將$賦值給jQuery,則讓jQuery重新有效。

如果需要對外提供接口,則在// 接口開始后面使用對象屬性的方式,將接口賦值給ex。注意一點(diǎn),ex返回后,你不可以通過接口改變插件內(nèi)部的變量,這個接口是對外接口。

利用OMD開發(fā)的步驟

1.在開始開發(fā)插件之前,將omd.js的代碼框架拷貝到你的項(xiàng)目(插件)文件中;

2.在注釋中對應(yīng)的位置開始撰寫你的腳步代碼

3.在注釋中指出接口輸出的位置處,通過ex.fun = function(){}的方式返回接口

4.完成代碼寫作之后,利用JavaScript壓縮工具,凈化和壓縮你的Javascript代碼

OMD使用要點(diǎn)

和sea.js不同,require.js的所有模塊都是異步加載,這意味著你不能按照以往的方式,通過先加載哪個模塊,然后加載另外一個模塊來確定它們的依賴關(guān)系。不幸的是,所有的jquery插件都要依賴jquery庫。因此,在require中需要解決好這個依賴問題。依賴的用法只有在define的參數(shù)中,前面已經(jīng)提到了define的幾種用法,我們來看下具體的實(shí)現(xiàn)方法:

define(["jquery"],function($){
    require(["plugin.omd.js"],function($plugin){
        $("#test").plugin();
        $plugin.p("#test");
    });
});

上面的代碼中,define(["jquery"])首先確定了這個模塊依賴于jquery,并將其返回接口以$作為變量。在這個基礎(chǔ)上,再去require(omd.js),則可以讓omd.js中的對jQuery的依賴可以實(shí)現(xiàn),omd.js中才可以正常使用jquery。

不過,從require.js的設(shè)計上,模塊之間都是異步加載的,如果按照上述方法解決依賴問題,性能上比sea.js要差很多。

我已經(jīng)將這個代碼放到github上,里面有demo,你可以看下plugin.js和main.js,來看看具體的用法。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/78597.html

相關(guān)文章

  • JavaScript」如何讓你的插件兼容CommonJS, AMD, CMD原生 JS

    摘要:模塊標(biāo)準(zhǔn)有三個全局變量和。模塊中有兩種方式提供對外的接口,一種是,一種是使用進(jìn)行返回。規(guī)范中,函數(shù)同樣有一個公有屬性。由于和都可以使用來定義對外接口,故可以合并成一句代碼。 模塊標(biāo)準(zhǔn) CommonJS CommonJS 有三個全局變量 module、exports 和 require。但是由于 AMD 也有 require 這個全局變量,故不使用這個變量來進(jìn)行檢測。 如果想要對外提供接...

    ShevaKuilin 評論0 收藏0
  • JavaScript塊化發(fā)展

    摘要:所有依賴這個模塊的語句,都定義在一個回調(diào)函數(shù)中,等到所有依賴加載完成之后前置依賴,這個回調(diào)函數(shù)才會運(yùn)行。如果將前面的代碼改寫成形式,就是下面這樣定義了一個文件,該文件依賴模塊,當(dāng)模塊加載完畢之后執(zhí)行回調(diào)函數(shù),這里并沒有暴露任何變量。 模塊化是我們?nèi)粘i_發(fā)都要用到的基本技能,使用簡單且方便,但是很少人能說出來但是的原因及發(fā)展過程。現(xiàn)在通過對比不同時期的js的發(fā)展,將JavaScript模...

    mengbo 評論0 收藏0
  • 一覽js塊化:從CommonJS到ES6

    摘要:模塊化規(guī)范有的模塊系統(tǒng)。規(guī)范是服務(wù)器端模塊的規(guī)范,由推廣使用。對于依賴的模塊,是提前執(zhí)行,是延遲執(zhí)行。瀏覽器廠商和都宣布要原生支持該規(guī)范。它將逐漸取代和規(guī)范,成為瀏覽器和服務(wù)器通用的模塊解決方案。 本文由云+社區(qū)發(fā)表 模塊化是指把一個復(fù)雜的系統(tǒng)分解到一個一個的模塊。 模塊化開發(fā)的優(yōu)點(diǎn): (1)代碼復(fù)用,讓我們更方便地進(jìn)行代碼管理、同時也便于后面代碼的修改和維護(hù)。 (2)一個單獨(dú)的文件就...

    antz 評論0 收藏0
  • 關(guān)于JavaScript模塊規(guī)范之CommonJSAMDCMD

    摘要:所有依賴這個模塊的語句,都定義在一個回調(diào)函數(shù)中,等到加載完成之后,這個回調(diào)函數(shù)才會運(yùn)行。也采用語句加載模塊,但是不同于,它要求兩個參數(shù)第一個參數(shù),是一個數(shù)組,里面的成員就是要加載的模塊第二個參數(shù),則是加載成功之后的回調(diào)函數(shù)。 本篇文章來自對文章《js模塊化編程之徹底弄懂CommonJS和AMD/CMD!》的總結(jié),大部分摘自文章原話,本人只是為了學(xué)習(xí)方便做的筆記,之后有新的體會會及時補(bǔ)充...

    binaryTree 評論0 收藏0
  • nodejs筆記-模塊機(jī)制

    摘要:模塊中定義的全局變量只作用于該文件內(nèi)部,不污染其他模塊。由純編寫的部分稱為內(nèi)建模塊,例等模塊部分使用編寫。兼容多種模塊規(guī)范檢測是否為或者檢測是否為或環(huán)境定義為普通模塊將模塊執(zhí)行結(jié)果掛載在對象下 1.為什么要CommonJS規(guī)范 javascript存在的缺點(diǎn) 沒有模塊系統(tǒng) 標(biāo)準(zhǔn)庫比較少 沒有標(biāo)準(zhǔn)接口 缺乏包管理系統(tǒng) CommonJS規(guī)范的提出,彌補(bǔ)了javascript沒有標(biāo)準(zhǔn)的缺...

    lscho 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<