2012-01-06 70 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