2012-09-06 254 views
4

我正在研究一个大的Backbone.js应用程序。该代码采用模块化结构,使用require.js。 现在我看到很多的骨干代码和教程这样做:将变量赋值给Backbone.js中的窗口对象

window.app = (window.app || {}); 

后,他们将指派模型定义和集合实例到全局对象,像这样:

Task = Backbone.Model.extend({ /*...*/ }); 
Tasks = Backbone.Collection.extend({ /*...*/ }); 

window.app.Task = Task; 
window.app.Tasks = new Tasks(); 
// do this with all your models and collections 

我喜欢这种方法对于其简单性以及无需处理何时何地实例化集合。但不知怎的,首先使用require.js将所有代码分配到一个全局变量(除了全局变量通常是javascript中的错误代码风格之外)之后,将代码分离成微小的比特似乎是错误的。

那么你对此有什么看法,这种方法有哪些优缺点?你如何处理Backbone中的对象?

回答

6

首先它不是那么大,污染您的全局命名空间,你可以在自己的名称空间包装所有模型中的一个问题:

app = (app || {}); 
app.Task = Backbone.Model.extend({ /*...*/ }); 
app.Tasks = Backbone.Collection.extend({ Model:app.Zask }); 

当谈到requirejs这取决于大小的项目。我认为对于较小的项目你可以没有。使用requirejs的好处并不在于防止名称空间污染,它的可维护性更好,因为您始终可以看到模块的依赖关系。你可以编写更好的单元测试,因为你可以测试一个模块和mock out all its dependencies。因此,我们从重建像上面的例子中的结构的大型骨干应用弄成这个样子:

型号/ Task.js

define(function() { 
    return Backbone.Model.extend({ /*...*/ }); 
}); 

收藏/ Tasks.js

define([models/Task], function (Task) { 
    return Backbone.Collection.extend({ Model:app.Task }); 
}); 

app.js

define([collections/Tasks], function (Tasks) { 
    var tasks = new Tasks(); 
    tasks.fetch(); 
}); 
+2

在requirejs中仍然使用'app'变量是否是传统的? –

1

我不同意全局变量在javascript中不好用;你需要大多数语言的全局变量。导入内容后,您需要能够引用它。类似Java的语言只是把所有的类名放到一个巨大的全局堆上;但你永远不会意识到这是因为在这些语言中,类(类名,类引用)不是变量。

在JavaScript类中(或假装模仿类的东西)只是您分配给变量的对象。所以,你要确保你可以在代码的其他部分引用它们。

现在,实际上在您的示例中,您将模型定义和集合实例(可能是单例)分配给全局范围。对于模型定义,我会说这是正确且唯一的方法(可能会添加一些命名空间,如window.app.model.Task = Task)。在第二种情况下,纯粹主义者的观点可能是它不太好。我宁愿做类似window.app.collection.Tasks = Tasks的事情,然后定义一个静态方法Tasks.getinstance(),它返回单例。或者,较不好的(但较少的编码)将把你的单身人士放在全球范围以及window.app.singletons.Tasks = Tasks()

最后,确保(因为我相信你有),所有这些都是正确的范围。此代码(在浏览器中运行)还将创建任务和任务全局对象。总结这件事的功能,并使用var

(function (app) { 
    var Task = Backbone.Model.extend({ /*....*/ }), 
    Tasks = Backbone.Collection.extend({ /*....*/ }, { 
    getInstance: function() { 
     if (!this.instance) { 
     this.instance = new Tasks(); 
     } 
     return this.instance; 
    } 
    }); 

    if (!app.models) { 
    app.models = {}; 
    } 
    if (!app.collections) { 
    app.collections = {}; 
    } 

    app.models.Task = Task; 
    app.collections.Tasks = Tasks; 
}(window.app)); 
0

我个人不会污染全局命名空间是沿AMD解决方案的线路。这里有一篇关于sharing resources across AMD modules的帖子,基本上你想要做什么,但有一个模型和收藏。

此外,在Backbone Aura框架的issue的底部,还有一个数据模块的实现,该模块用于检索命名空间集合和模型。我刚刚在我的应用程序中遇到了这个问题,这是我计划实施的。