2012-01-06 67 views
33

我創建了一個JavaScript應用程序,其中包含一個文件中的所有代碼。該應用程序已經有了很大的發展,我認爲是時候把它分成多個文件,但我很難搞清楚如何做到這一點。我認爲問題在於我怎麼決定構建應用程序,它使用了下面的模板:如何將JavaScript應用程序拆分爲多個文件?

var myApp = function(){ 

    //there are several global variables that all of the modules use; 
    var global1, global2, module1, module2; 

    global1 = { 
     prop1:1 
    }; 

    //There are also several functions that are shared between modules 
    function globalFunction(){ 

    } 

    var ModuleOne = function(){ 

     function doSomething(){ 
      //using the global function 
      globalFunction(); 
     } 

     return{ 
      doSomething:doSomething 
     } 
    }; 

    var ModuleTwo = function(){ 

     function doSomething(){ 
      //module 2 also needs the global function 
      globalFunction(); 

      //Use the functionality in module 1 
      //I can refactor this part to be loosely coupled/event driven 
      module1.doSomething(); 
     } 
    }; 

    module1 = new ModuleOne(); 
    module2 = new ModuleTwo(); 
}; 

即使所有的模塊都鬆散耦合和事件驅動的,我還是不知道怎麼會有我在每個模塊依賴共享函數/變量的情況下,將其分解爲多個文件。有沒有人有建議?

+0

儘管如此,工具如[module8] (https://github.com/clux/modul8)解決你的問題 – Raynos 2012-01-06 02:25:39

+0

看看這篇文章中的設計模式:http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-深度 - 你可以將模塊定義分割爲多個文件,以便共享通用屬性,還可以創建僅針對特定文件的變量或方法。 – nnnnnn 2012-01-06 02:30:33

+0

@nnnnnn謝謝。我會立即檢查出來。 – 2012-01-06 03:21:34

回答

34

看看本文中的設計模式:http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth - 你可以在一個方式跨多個文件分割你的模塊定義讓共同的屬性可以共享,但也可以讓你創建只對特定文件是私有的變量或方法。

的基本思路是,個別JS文件添加到同一模塊的代碼是這樣的:

var MODULE = (function (my) { 
    var privateToThisFile = "something"; 

    // add capabilities... 

    my.publicProperty = "something"; 

    return my; 
}(MODULE || {})); 

凡在每個JS文件,如果MODULE已被定義(從另一個JS文件),你給它添加否則你創建它。你可以設置它,以便它(大部分)無關,包括各種文件的順序。

本文詳細介紹了幾種變體,當然你可能會想出自己的調整...

1

給require.js一槍。 http://requirejs.org/

例子:

require(["dir/file"], function() { 
    // Called when file.js loads 
}); 
+0

是的,我研究過它,但我仍然不知道如何解決共享函數的問題... – 2012-01-06 02:22:58

+0

但是,這如何幫助拆分目前相互依賴的代碼的大文件? – nnnnnn 2012-01-06 02:25:46

+0

您爲每個類創建一個文件(因此是OOP標記),並且運行的腳本只需將這些類用於使用即可。如果您向我展示代碼,我可以幫助您將其分發到各個文件中。 – 2012-01-06 02:29:24

2

你可以把共享功能和共享模塊對myApp對象,使他們不污染全局命名空間,但可以不被同一封閉內的任何地方訪問。

myApp.moduleOne = function() {...} 
myApp.moduleTwo = function() {...} 
myApp.globalFunction = function() {...} 

然後,您可以在任何文件中定義它們並在任何文件中使用它們。

您也可以將文件分成多個文件,但要求將它們包含在保留關閉的特定順序中。如果您爲了實際編輯的原因而分解文件,但是爲了實際部署而重新組合並最小化它們,那麼就代碼編寫或如何部署而言,這不會花費任何代價,但會爲您提供大量較小的文件編輯方便。

+0

myApp不是真名,我只是用它作爲例子。考慮到你的建議,我需要將每次調用globalFunction改爲myApp.globalFunction()是否正確? – 2012-01-06 02:35:01

+0

@MarkBrown - 正確。編寫代碼時不太理想,但是可以更靈活地將代碼分割成完全獨立的獨立文件。我也給我的答案增加了另一個選項。 – jfriend00 2012-01-06 02:37:50

0

我最喜歡的解決方案是使用服務器端腳本在我的「主」文件中包含其他文件。例如,使用Perl的模板工具包:

var myApp = function(){ 
    [% INCLUDE lib/module1.js %] 
    [% INCLUDE lib/module2.js %] 
    [% INCLUDE lib/module3.js %] 
} 

或PHP:

var myApp = function(){ 
    <?php 
    include 'lib/module1.js'; 
    include 'lib/module2.js'; 
    ?> 
} 
+1

這是動態構建javascript。應該避免使用靜態編譯而不是動態包含。 – Raynos 2012-01-06 02:56:15

+0

TT和PHP都可以從控制檯運行,所以如果你想靜態編譯,你可以輕鬆編寫一個構建腳本。哦,加TT可以配置爲緩存文件,所以編譯只需要發生一次。 – slebetman 2012-01-06 02:57:46

4

不要加入混淆,但來自C++背景,我試圖按照下面描述的方式構建類似於C++名稱空間的東西。它的工作原理,但我想知道這是否是OP的可接受模式?

-------------------------------- file main。js:----------------

var namespacename = function(){} 

namespacename.mainvalue = 5; 

namespacename.maintest = function() { 
    var cm = new namespacename.game(); 
    cm.callme(); 
} 

------------------------- ------- file game.js:----------------

namespacename.gamevalue = 15; 

namespacename.game = function(){ 
    this.callme = function(){ 
     console.log("callme"); 
    } 
} 

namespacename.gametest = function() { 
    console.log("gametest:gamevalue:" + this.gamevalue); 
    console.log("gametest:mainvalue:" + this.mainvalue); 
} 

--------------- ----------------- file index.html:--------------

<html> 
    <head> 
     <title>testbed</title> 
    </head> 

    <body onload="init();"> 
    </body> 

    <script type="text/javascript" src="main.js"></script> 
    <script type="text/javascript" src="game.js"></script> 

    <script type="text/javascript"> 

     init = function() 
     { 
      namespacename.maintest(); 
      namespacename.gametest(); 

      console.log("html main:" + namespacename.mainvalue); 
      console.log("html game:" + namespacename.gamevalue); 
     } 

    </script> 
</html> 
+4

爲什麼將_namespacename_聲明爲從未調用過的空函數?你可以用_var namespacename = {} _將它聲明爲空對象,其餘代碼不需要改變。 – nnnnnn 2013-09-10 23:02:23

+0

該解決方案適用於我! – 2016-04-11 14:46:44