2014-03-05 29 views
7

我正在嘗試使用Require.js製作外部庫。感謝Require.js not compiling single js file correctlyRequire.js (almond.js) Timing Off我已經想出瞭如何讓所有內容「編譯」到單個優化/構建的文件中,並且該單個文件起作用。只有一個問題:我無法弄清楚如何爲我的庫設置一個變量。如何從Require.js中導出全局變量?

假設我想讓我的圖書館創建window.Foo。我試圖用一個main.js文件有:

window.Foo = require([], function() { 
    window.Foo = {someValue: 1}; 
    return {someValue: 2}; 
}); 

和一個包裝末端片段:

return require('main'); 
})); 

正如你所看到的,我試圖從內明確設置window.Foo暴露美孚全球空間都require調用,並通過結束片段的返回值從外部顯式設置它。但是沒有一個工作;如果我在加載構建文件後立即添加console.log(window.foo),它會告訴我window.Foo未定義。

如果我做了一個window.setTimeout window.Foo最終確實設置(到{someValue: 1}),但我不能很好地期待我的用戶必須用超時來包裝他們所有的代碼。任何人都可以請解釋我如何可以得到window.Foo一旦我的優化/構建文件加載被定義?

+0

是在庫中使用RequireJS有什麼特別的原因嗎?支持RequireJS和CommonJS可能會更好,並且可以像現在大多數圖書館一樣支持全局設置。 – jgillich

+0

我們的主代碼庫使用了Require,而這個外部庫使用了幾個代碼庫。爲了使外部庫充分利用我們主代碼庫中的現有代碼,它需要能夠「說出」需求......儘管一旦它獲得代碼,它就不需要任何要求,這就是爲什麼我要試圖讓用戶看起來像是一個完全獨立的庫。 – machineghost

回答

11

如果按照James的指導here,你可以很容易地製作設計庫作爲一些RequireJS模塊,可以讓某些人可以同步加載。

我有一個github repository說明了整個事情。要點:

  • main模塊出口Foo全球空間:

    define('main', ["./modC"], function() { 
    
    console.log("inside"); 
    window.Foo = {someValue: 1}; 
    
    return {someValue: 2}; 
    
    }); 
    

    它還返回由開始的片段導出爲Bar(這是說root.Bar = factory();線)的值。所以它說明了出口到全球空間的兩種方式。

  • 通過r.js開始主要用require同步形式使用的包裝代碼:

    require(`main`); 
    

如果加載它,你會看到下面的輸出:

outside 
loaded modC 
inside 
out in the HTML! 
value of window.Foo: Object {someValue: 1} 
value of window.Bar: Object {someValue: 2} 
+0

啊,謝謝你的代碼示例:我想我有一個'require',我應該有一個'define'。我會在今天早上有空的時候儘快實施你的方法。 – machineghost

+0

除了這個答案(這對我來說很好,謝謝路易斯),在一個需求問題線程中的人也指出了這個庫(所以我提到它的完整性):https://github.com/gfranko/ amdclean – machineghost

+0

'窗口'沒有工作(phonegap)'文檔'沒有工作 –

3

呼叫至require()異步,這意味着你傳遞作爲參數的函數的返回值是通過require()本身返回。你的問題可能會以不同的方式來解決,RequireJS方式是定義你的代碼模塊中,並要求它作爲一個依賴:

// mymodule.js 
define([], function() { 
    window.Foo = {someValue: 1}; 
    return {someValue: 2}; 
}); 

// main.js 
require(['mymodule'], function (mymodule) { 
    console.log(window.Foo); // {someValue: 1} 
    console.log(mymodule); // {someValue: 2} 
}); 
+2

沒錯,但是我必須讓我的用戶使用Require。這是他們之間的區別,只是能夠將庫添加到頁面並調用'Foo.bar()'與使它們加載require然後執行'require(['fooLibrary'],(Foo){Foo.bar() ;});'。大多數人習慣於前者:他們下載jQuery,然後使用'$'...他們不必'require(['jQuery'],function($){$ .doSomething()});'。理想情況下,我希望我們的庫以相同的方式工作,並且因爲我已提前將所有內容一起預先編譯到單個文件中,理論上應該不需要任何異步性。 – machineghost

+1

@machineghost jquery在構建過程中完全按照你的需要進行,但它並沒有被RequireJS本身支持:https://github.com/jquery/jquery/blob/master/build/tasks/build.js – jgillich

+0

呵呵,這太有趣了。不過,我有點震驚,它不可能將某些Require.js代碼轉換爲同步代碼;需要優化器獲得95%的代碼... – machineghost