随着像jQuery这样的JavaScript框架使客户端web应用程序更丰富,功能更强大,我开始注意到一个问题…

你到底是怎么组织起来的?

把所有的处理程序放在一个地方,并为所有事件编写函数? 创建函数/类来包装您的所有功能? 疯狂地写作,只希望结果是最好的? 放弃,找一份新工作?

我提到了jQuery,但它实际上是一般的JavaScript代码。我发现,当一行一行开始堆积时,管理脚本文件或找到您要找的内容变得越来越困难。我发现的最大问题可能是,做同一件事有太多的方法,很难知道哪一种是目前普遍接受的最佳实践。

有什么通用的建议可以让你的.js文件像你的应用程序的其他部分一样漂亮整洁吗?或者这只是IDE的问题?还有更好的选择吗?


EDIT

这个问题主要是关于代码组织,而不是文件组织。有一些合并文件或拆分内容的好例子。

我的问题是:目前普遍接受的组织实际代码的最佳实践方式是什么?您的方法是什么,甚至推荐的方法是什么,以与页面元素交互并创建互不冲突的可重用代码?

有些人列出了名称空间,这是个好主意。还有什么其他方法,更具体地说,处理页面上的元素并保持代码的组织和整洁?


当前回答

好的OO + MVC原则对于管理一个复杂的javascript应用程序肯定大有帮助。

基本上,我将我的应用程序和javascript组织成以下熟悉的设计(从我的桌面编程到Web 2.0一直存在)

图像上数值的说明:

Widgets representing the views of my application. This should be extensible and separated out neatly resulting good separation that MVC tries to achieve rather than turning my widget into a spaghetti code (equivalent in web app of putting a large block of Javascript directly in HTML). Each widget communicate via others by listening to the event generated by other widgets thus reducing the strong coupling between widgets that could lead to unmanageable code (remember the day of adding onclick everywhere pointing to a global functions in the script tag? Urgh...) Object models representing the data that I want to populate in the widgets and passing back and forth to the server. By encapsulating the data to its model, the application becomes data format agnostics. For example: while Naturally in Javascript these object models are mostly serialized and deserialized into JSON, if somehow the server is using XML for communication, all I need to change is changing the serialization/deserialization layer and not necessarily needs to change all the widget classes. Controller classes that manage the business logic and communication to the server + occasionally caching layer. This layer control the communication protocol to the server and put the necessary data into the object models Classes are wrapped neatly in their corresponding namespaces. I am sure we all know how nasty global namespace could be in Javascript.

In the past, I would separate the files into its own js and use common practice to create OO principles in Javascript. The problem that I soon found that there are multiple ways to write JS OO and it's not necessarily that all team members have the same approach. As the team got larger (in my case more than 15 people), this gets complicated as there is no standard approach for Object Oriented Javascript. At the same time I don't want to write my own framework and repeat some of the work that I am sure smarter people than I have solved.

jQuery是非常好的Javascript框架,我喜欢它,但随着项目越来越大,我显然需要额外的结构为我的web应用程序,特别是促进标准化OO实践。就我自己而言,经过几次试验,我发现YUI3 Base和Widget (http://yuilibrary.com/yui/docs/widget/和http://yuilibrary.com/yui/docs/base/index.html)基础设施完全满足了我的需要。我使用它们的几个原因。

It provides Namespace support. A real need for OO and neat organization of your code It support notion of classes and objects It gives a standardize means to add instance variables to your class It supports class extension neatly It provides constructor and destructor It provides render and event binding It has base widget framework Each widget now able to communicate to each other using standard event based model Most importantly, it gives all the engineers an OO Standard for Javascript development

与许多观点相反,我不一定要在jQuery和YUI3之间做出选择。这两者可以和平共处。虽然YUI3为我复杂的web应用程序提供了必要的OO模板,但jQuery仍然为我的团队提供了我们都喜欢和熟悉的易于使用的JS抽象。

使用YUI3,我成功地创建了MVC模式,通过分离将Base扩展为模型的类,将Widget扩展为视图的类,当然还有进行必要逻辑和服务器端调用的控制器类。

Widget可以使用基于事件的模型相互通信,并根据预定义的接口侦听事件并执行必要的任务。简单地说,把OO + MVC结构的JS是一个乐趣对我来说。

声明一下,我不是为雅虎工作的!仅仅是一个建筑师在试图解决最初的问题所带来的问题。我认为如果有人找到了等效的OO框架,这也可以。基本上,这个问题也适用于其他技术。感谢所有提出OO原则+ MVC的人,使我们的编程更易于管理。

其他回答

按需加载所需的代码。谷歌对他们的Google .loader做了类似的事情

我的老板仍然在谈论他们编写模块化代码(C语言)的时代,并抱怨现在的代码是多么糟糕!据说程序员可以在任何框架中编写程序集。总有一种策略可以克服代码组织。最基本的问题是那些把java脚本当作玩具的人,从来没有尝试去学习它。

在我的例子中,我在UI主题或应用程序屏幕的基础上编写js文件,使用适当的init_screen()。使用适当的id命名约定,我确保在根元素级别上没有名称空间冲突。在不引人注目的window.load()中,我根据顶级id将内容绑定起来。

我严格使用java脚本闭包和模式来隐藏所有私有方法。这样做之后,再也没有遇到属性/函数定义/变量定义冲突的问题。然而,当与团队一起工作时,通常很难执行同样的严格性。

我很惊讶没有人提到MVC框架。我一直在使用Backbone.js来模块化和解耦我的代码,这是非常宝贵的。

有相当多这样的框架,其中大多数也非常小。我个人的观点是,如果您想为华丽的UI编写几行jQuery以外的东西,或者想要一个丰富的Ajax应用程序,那么MVC框架将使您的工作更加轻松。

我认为这可能与DDD(领域驱动设计)有关。我正在开发的应用程序,虽然缺乏正式的API,但确实通过服务器端代码(类/文件名等)给出了提示。有了这些,我创建了一个顶级对象作为整个问题域的容器;然后,我在需要的地方添加名称空间:

var App;
(function()
{
    App = new Domain( 'test' );

    function Domain( id )
    {
        this.id = id;
        this.echo = function echo( s )
        {
            alert( s );
        }
        return this;
    }
})();

// separate file
(function(Domain)
{
    Domain.Console = new Console();

    function Console()
    {
        this.Log = function Log( s )
        {
            console.log( s );
        }
        return this;
    }
})(App);

// implementation
App.Console.Log('foo');

我尽量避免在HTML中包含任何javascript。所有代码都封装在类中,每个类都在自己的文件中。对于开发,我有单独的<script>标记来包含每个js文件,但是它们被合并到一个更大的包中用于生产,以减少HTTP请求的开销。

通常,我会为每个应用程序创建一个“main”js文件。所以,如果我正在编写一个“调查”应用程序,我将有一个名为“survey.js”的js文件。这将包含进入jQuery代码的入口点。我在实例化期间创建jQuery引用,然后将它们作为参数传递到我的对象中。这意味着javascript类是“纯粹的”,不包含任何对CSS id或类名的引用。

// file: survey.js
$(document).ready(function() {
  var jS = $('#surveycontainer');
  var jB = $('#dimscreencontainer');
  var d = new DimScreen({container: jB});
  var s = new Survey({container: jS, DimScreen: d});
  s.show();
});

我还发现命名约定对于可读性很重要。例如:我在所有jQuery实例前加'j'。

在上面的例子中,有一个类叫做DimScreen。(假设这会使屏幕变暗并弹出一个警告框。)它需要一个div元素,它可以放大以覆盖屏幕,然后添加一个警告框,因此我传入一个jQuery对象。jQuery有一个插件概念,但它似乎有局限性(例如,实例不是持久的,不能访问),没有真正的好处。因此,DimScreen类将是一个标准的javascript类,只是恰好使用jQuery。

// file: dimscreen.js
function DimScreen(opts) { 
   this.jB = opts.container;
   // ...
}; // need the semi-colon for minimizing!


DimScreen.prototype.draw = function(msg) {
  var me = this;
  me.jB.addClass('fullscreen').append('<div>'+msg+'</div>');
  //...
};

我已经使用这种方法构建了一些相当复杂的应用程序。