我最近遇到了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并创建了我们数据模型的基本工作表示(这涉及创建一个与Require JS一起使用的垫片)。实质上这是有效的。所以我扩展了示例,以便Model C也可以拥有Collection C的实例(自引用)。这似乎再次起作用。优秀。但是,将示例应用于我的应用程序更加困难 - 将模型和集合拆分为单个文件证明更加困难,因为主干关系要求集合和模型名称位于全局名称空间(使用Require和“use strict”有点棘手) 。由于我们的复杂数据模型,我想使用字符串标识符来表示关系,而不是显式的需求引用,这也证明是困难的。我尝试将所有内容添加到exports命名空间,但这又不起作用。无论如何,我认为通过将集合和模型添加到自定义命名空间,然后将此命名空间添加到backbonerelational模型范围,我找到了一个解决方案。我把我的自定义库命名为“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;
});
集合/ 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,那么我必须将所有这些引用为require依赖项。有更好的方法吗?
答案 0 :(得分:1)
我实际上已经停止使用Backbone Relational,现在我正在使用JJRelational,因为它允许多对多关系。我还通过创建一个名为“relational.js”的新文件来否定从主应用程序文件中引用集合和模型的需要,该文件引用集合和模型并将它们作为对象的属性返回。这样,如果我需要新的模型或集合,我只需要“relational.js”。
我的relational.js文件看起来有点像这样:
define([
// Models
"models/broadcast",
"models/version",
// Collections
"collections/broadcasts",
"collections/versions"
], function(
// Models
Broadcast,
Version,
// Collections
Broadcasts,
Versions
) {
"use strict";
var _relational = {
Broadcast: Broadcast,
Version: Version,
Broadcasts: Broadcasts,
Versions: Versions,
};
// Register the Collections
Backbone.JJRelational.registerCollectionTypes({
"Broadcasts": _relational.Broadcasts,
"Versions": _relational.Versions
});
// Provide JJRelational with model scope - pull request submitted to JJRelational to handle this
Backbone.JJStore.addModelScope(_relational);
return _relational;
});
然后在我的主app.js中:
define(["libs/relational"], function(Relational){
var broadcast = new Relational.Broadcast();
});
答案 1 :(得分:0)
你有没有提过Backbone Associations。我建议你看看一次。
当我使用它时,我遇到了类似的循环依赖和自引用问题。原因是我已将客户端Models
映射到后端的Beans
,后者使用Tables
映射到Hibernate
。在one-to-many
中指定Hibernate
关系时,您需要将一个实体的引用指定为其他实体,反之亦然。然后,当Jersey服务返回这些实体时,转换为JSON具有循环依赖性。我可以使用some annotations在后端进行删除。但是没有办法在Backbone
方面解决它。我向Backbone Associations
的作者提出了这个问题并修复了它。
希望这在某些方面有所帮助。