Backbone有没有RequireJS:用什么封装数据更好?

Backbone with or without RequireJS: What is better for data encapsulation?

我正在将我的 'regular' Backbone 项目转换为 Backbone 和 RequireJS 的组合。虽然这个过程非常完美,但我仍然有一个问题。

之前我为我的应用程序声明了一个全局名称空间,然后我将所有模型绑定到该名称空间,查看集合。这是我实际上从 Backbone ToDoMVC project.

得到的提示

例如,视图的 initialize 方法可能如下所示:

initialize: function () {
  app.employees = new app.EmployeeCollection();
  app.employees.fetch();
}

之所以可行,是因为在每个文件的开头,我都这样做了:

var app = app || {};

现在,当我将文件定义为 AMD 模块时,app 命名空间不再存在,这意味着一切都更加封装:

initialize: function () {
  var employees = new EmployeeCollection();
  employees.fetch();
}

EmployeeCollection 加载了 RequireJS:

var EmployeeCollection = require('collections/EmployeeCollection');

不幸的是,我对 Backbone 和一般的 MVC 还是很陌生,所以我不确定这是好事还是坏事。

这会对我的项目产生什么影响 – 是否可以像我以前那样使用应用命名空间,或者这是否会破坏任何 MVC/OOP 'rule'?我需要注意任何 Backbone 特定后果吗?

是的,通过 requirejs 加载 EmployeeCollection 是一件好事。这明确列出了每个模块的依赖项,并让 requirejs 帮助您以正确的顺序加载模块。

app 命名空间方法和 requirejs 方法都有效。 Backbone 不会关心您采用哪种方法,因为您可以使用必要的 View/Collection/Model 构造函数。就我个人而言,我喜欢我提到的 requirejs 的上述好处,但这是你必须决定的个人偏好。

但是,您不应该同时使用 requirejs 和一个无所不知的应用命名空间。如果您致力于 requirejs,那么您应该只将 app 命名空间与您的大多数应用程序需要的顶级数据一起使用,而不是将所有 requirejs 模块附加到它。

例如,您可以将它用于包含有关当前用户的信息的全局 UserModel。为此,您需要创建一个应用程序对象作为 requirejs 模块,就像您对 EmployeeCollection 所做的那样,然后构建 UserModel 的任何模块都需要 'app' 并执行一个简单的赋值:app.user=user。

我说过要谨慎执行此操作,因为为所有模块使用全局应用程序名称空间会牺牲 requirejs 的大部分好处,并会给您带来一些排序痛苦。即:

  • 您无法再以声明方式查看每个模块的实际依赖关系,也无法轻松可视化所有模块如何组合在一起。而不是在 'collections/EmployeeCollection' 中需要你的视图(或任何东西)的初始化函数,你需要 'app';那里没有太多上下文。
  • Requirejs 将首先负责加载所需的模块,然后再允许您定义函数 运行。但是,如果一切都只需要 'app' 那么 requirejs 只会确保首先定义 'app' 并且你自己完成其他所有事情。如果 app.Bar 需要 app.Foo,您必须做一些事情以确保首先加载和定义 app.Foo。
  • 类似地,如果 requirejs 无法弄清楚你所有的依赖关系,因为一切都只需要 'app' 那么 requirejs 的 javascript 连接器和优化器工具(称为 r.js)将是要么对您无用,要么需要大量维护才能将所有模块添加到它应该编译的列表中。

如果您决定使用 requirejs,请接受它可以为您做的事情,只需要在您想要的模块中使用,而不是严重依赖全局名称空间。但这两种方法之间没有正确或错误的选择。每个都被很多聪明人使用。