我正在开发一个很大的Backbone.js应用程序。代码使用require.js
进行模块化结构化。
现在我看到很多骨干代码和教程都在这样做:
window.app = ( window.app || {} );
之后,他们会将模型定义和Collection实例分配给该全局对象,如下所示:
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中处理你的对象?
答案 0 :(得分:6)
首先,污染全局名称空间并不是一个大问题,因为您可以将所有模型包装在自己的命名空间中:
app = (app || {} );
app.Task = Backbone.Model.extend({ /*...*/ });
app.Tasks = Backbone.Collection.extend({ Model:app.Zask });
当涉及到requirejs时,它取决于项目的大小。我认为对于较小的项目,你可以不用。使用requirejs的好处不是防止命名空间污染,它的可维护性更好,因为你总能看到模块的依赖关系。您可以编写更好的单元测试,因为您可以测试模块和mock out all its dependencies。因此,我们从上面的示例结构重建了一个大型Backbone应用程序,如下所示:
<强>模型/ 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();
});
答案 1 :(得分:1)
我不同意全局变量在javascript中很糟糕;你需要大多数语言的全局变量。导入内容后,您需要能够引用它。类似Java的语言只是将所有类名称抛到一些巨大的全局堆上;但你从来没有意识到这是因为在那些语言中,类(类名,类引用)不是变量。
在javascript类中(或假装模仿类的东西)只是您分配给变量的对象。因此,您可以确保在代码的其他部分中引用它们。
现在,实际上在您的示例中,您将模型定义和集合实例(可能是单例)分配给全局范围。对于模型定义,我会说这是正确且唯一的方法(可能添加一些命名空间,例如window.app.model.Task = Task
)。在第二种情况下,纯粹主义者的观点可能是它不太好。我更喜欢做window.app.collection.Tasks = Tasks
之类的东西,然后定义一个返回单例的静态方法Tasks.getinstance()
。或者,不那么好(但编码较少)就是将你的单身人士放在全球范围内window.app.singletons.Tasks = Tasks()
。
最后,确保(因为我确定你有)所有这些都是适当的范围。此代码(在浏览器中运行)也将使Task和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));
答案 2 :(得分:0)
我个人不会污染AMD解决方案的全局命名空间。这是sharing resources across AMD modules上的一篇文章,它基本上是你想要做的,但有一个模型和集合。
此外,在这个issue的Backbone Aura框架的底部,有一个数据模块的实现,该命令用于命名集合和模型以进行检索。我前几天在我的应用程序中遇到了这个问题,这是我计划实施的。