【发布时间】:2014-02-06 03:59:12
【问题描述】:
我最近遇到了 Backbone 和 Require JS 的问题,因为我们有一个相当复杂的数据模型,我需要表示它导致循环依赖和自引用的问题。我已经在网上阅读了很多帖子(没有一个真正有效),但我想我已经找到了解决方案。因此,我想分享这一点,希望它可以帮助遇到这个问题的人,但也想问你们是否认为有办法收拾东西。
第一个问题是我有引用集合的模型,这些模型引用了引用集合的模型,所有这些都创建了一个很大的混乱循环依赖。坦率地说,这只是破坏了应用程序。这是一个伪代码示例:
Model A
has Collection B
Collection B
of Model B
Model B
has Collection A
has Collection C
Collection A
of Model A
Collection C
of Model C
Backbone docs 声明这可以通过以下方式实现:
initialize: function() {
this.messages = new Messages;
this.messages.url = '/mailbox/' + this.id + '/messages';
this.messages.on("reset", this.updateCounts);
},
我尝试了各种方法来满足我们的需求,但我们复杂的嵌套需求打破了 Backbone。所以我偶然发现了backbone relational,并为我们的数据模型创建了一个基本的工作表示(这涉及创建一个 shim 以使用 Require JS)。从本质上讲,这奏效了。所以我扩展了这个例子,这样 Model C 也可以有 Collection C 的实例(自我引用)。这似乎再次奏效。优秀。但是,将示例应用于我的应用程序更加困难 - 将模型和集合拆分为单独的文件被证明更加困难,因为骨干关系期望集合和模型名称位于全局命名空间中(对于 Require 和“使用严格”有点棘手) .由于我们的数据模型复杂,我想使用字符串标识符来表示关系以进行前向引用,而不是显式的要求引用,这也被证明是困难的。我尝试将所有内容添加到导出命名空间,但这同样不起作用。无论如何,我认为通过将集合和模型添加到自定义命名空间,然后将此命名空间添加到骨干关系模型范围,我找到了解决方案。我已将我的自定义库命名为“Orca”(因为虎鲸实在是太棒了)。
bootstrap.js
require.config({
paths: {
"jquery" : "../bower_components/jquery/jquery",
"underscore" : "../bower_components/underscore-amd/underscore",
"backbone" : "../bower_components/backbone-amd/backbone",
"relational" : "../bower_components/backbone-relational/backbone-relational",
...
shim: {
"underscore": {
exports: "_"
},
"backbone": {
deps: ["underscore", "jquery"],
exports: "Backbone"
},
"relational": {
deps: ["backbone"]
},
...
app.js
define(["backbone", "relational", "libs/orca", "collections/a", "models/a", "collections/b", "models/b", "collections/c", "models/c"], function(Backbone, Relational, Orca){
"use strict";
var App = function(options) {
this.initialize(otions);
};
App.prototype = _.extend(Backbone.Events, {
initialize: function(options) {
Orca.initialize();
var a = new Orca.Relational.ModelA([],{});
}
}
return App;
});
lib/orca.js
define(["backbone", "relational"], function(Backbone) {
"use strict";
var Orca = {
Relational: {},
initialize: function() {
Backbone.Relational.store.addModelScope(this.Relational);
}
};
// I actually extend Backbone.RelationalModel so I can have custom methods,
// e.g. "parse" but I've simplified the code for example's sake...
Orca.Model = Backbone.RelationalModel;
Orca.Collection = Backbone.Collection;
return Orca;
});
collections/a.js
define(["backbone", "libs/orca"], function(Backbone, Orca) {
"use strict";
Orca.Relational.CollectionA = Backbone.Collection.extend({});
});
模型/a.js
define(["backbone", "libs/orca"], function(Backbone, Orca) {
"use strict";
Orca.Relational.ModelA = Orca.Model.extend({
relations: [
{
type: Backbone.HasMany,
key: "bs",
relatedModel: "ModelB",
includeInJSON: Backbone.Model.prototype.idAttribute,
collectionType: "CollectionB",
reverseRelation: {
key: "a"
}
}
]
});
});
CollectionB 和 ModelB 相似,因此为简洁起见,我省略了这些。
为了展示自我参照:
define(["backbone", "libs/orca"], function(Backbone, Orca) {
"use strict";
Orca.Relational.ModelC = Orca.Model.extend({
relations: [
{
type: Backbone.HasMany,
key: "cs",
relatedModel: "ModelC",
includeInJSON: Backbone.Model.prototype.idAttribute,
collectionType: "CollectionC",
reverseRelation: {
key: "c"
}
}
]
});
});
所以我对这段代码的错误是在 app.js 中我创建了一个新的 ModelA 实例。但是因为这引用了 CollectionB,而 ModelB 又使用了 ModelB,而 ModelB 又引用了 Collection C 并使用了 Model C,所以我必须将所有这些引用为必需的依赖项。有没有更好的方法来做到这一点?
【问题讨论】:
-
也许将集合和模型添加到“窗口”对象可能会消除对自定义对象的需求,但我喜欢将事物排除在全局对象之外的想法
标签: javascript backbone.js circular-dependency backbone-relational self-reference