我是BackboneJS的新手,我一直使用带有RequireJS的Backbone关系模型来处理嵌套关系——我想我遇到了循环问题。如有任何帮助,我们将不胜感激!
我有以下型号和系列:
/* Module Model at models/module*/
define([
'jquery',
'underscore',
'backbone',
'backboneRelational',
], function($, _, Backbone) {
var ModuleModel = Backbone.RelationalModel.extend({
urlRoot: 'api/module',
_radius: 50,
relations: [{
type: Backbone.HasMany,
key: 'children',
relatedModel: 'ModuleModel',
collectionType: 'ModuleCollection',
reverseRelation: {
key: 'parent_id',
includeInJSON: 'id'
}
}],
url: function() {
return this.id? 'api/module/' + this.id : 'api/module';
}
});
return ModuleModel;
});
/* Module Collection */
define([
'jquery',
'underscore',
'backbone',
'models/module'
], function($, _, Backbone, ModuleModel) {
var ModuleCollection = Backbone.Collection.extend({
model: ModuleModel,
url: 'api/modules'
});
return ModuleCollection;
});
当我初始化对象ModuleModel时,它会抛出以下错误:
Relation=child; no model, key or relatedModel (function (){ parent.apply(this, arguments); }, "children", undefined)
你能给我指正确的方向吗?
这看起来像是一个范围界定问题。在初始化ModuleModel
的过程中,它想与自己创建一个hasMany
关系,但它找不到自己,它会以所述错误的形式给你带来悲伤:
http://jsfiddle.net/yNLbq
一旦对象可以从当前范围到达,事情就会开始解决:
http://jsfiddle.net/jDw5e
一个可能的解决方案是为模型和集合本身提供一个可以从当前范围访问的命名空间。
希望这能有所帮助。
我在这里遇到了这个问题:RequireJS+BackboneRelational+Self Referential。他似乎从这个帖子中继承了一些问题,所以我想我可以加一角钱。
首先,由于您使用的是RequireJS,因此没有全局变量。您不能简单地提供对象的名称,您需要为relatedModel
和collectionType
提供实际的对象引用。
您最棘手的问题是ModuleModel
的relatedModel
实际上是ModuleModel
本身,当您将其分配给relatedModel
(使用AMD模型)时,不会定义它。您必须将分配推迟到分配ModuleModel
之后。
最后,您需要解析循环引用。dokkaebi建议使用exports
是正确的,但他的实现实际上滥用了exports
。导出时,按照他的建议将对象直接附加到exports
,但导入时需要引用模块才能使用它,而不是exports
。
这应该有效:
ModuleModel.js
define(['exports', 'ModuleCollection'], function (exports, Module) {
'use strict';
var ModuleModel = Backbone.RelationalModel.extend({
urlRoot: 'api/module',
_radius: 50,
relations: [{
type: Backbone.HasMany,
key: 'children',
// ModuleModel is undefined; this line is useless
// relatedModel: ModuleModel,
// no globals in require; must use imported obj ref
collectionType: Module.Collection,
reverseRelation: {
key: 'parent_id',
includeInJSON: 'id'
}
}],
url: function() {
return this.id? 'api/module/' + this.id : 'api/module';
}
});
// Now that `ModuleModel` is defined, we can supply a valid object reference:
ModuleModel.prototype.relations[0].relatedModel = ModuleModel;
// Attach `Model` to `exports` so an obj ref can be obtained elsewhere
exports.Model = ModuleModel;
});
ModuleCollection.js
define(['exports', 'ModuleModel'], function(exports, Module) {
'use strict';
var ModuleCollection = Backbone.Collection.extend({
// must reference the imported Model
model: Module.Model,
url: 'data.php' // <-- or wherever
});
// Attach `Collection` to `exports` so an obj ref can be obtained elsewhere
exports.Collection = ModuleCollection;
});
Main.js
define(['ModuleCollection'], function(Module) {
'use strict';
var modules = new Module.Collection();
modules.fetch().done(function() {
modules.each(function(model) {
console.log(model);
});
});
});
来自backbon-rerelational.js v0.5.0(第375行)中的注释:
//"exports"应该是全局对象,如果以字符串形式给定,则可以在其中找到"relatedModel"。
如果在define调用中需要特殊的"exports"值作为依赖项,然后在返回之前将模块放置在exports对象上,则可以将该模块作为字符串或exports的成员引用。
在ModuleModel.js:中
define(['exports', 'use!backbone', 'use!backbone-relational'], function(exports, Backbone) {
var ModuleModel = Backbone.RelationalModel.extend({
relations: [
{
type: Backbone.HasMany,
key: 'groups',
relatedModel: 'ModuleModel',
collectionType: 'ModuleCollection'
}
]
});
exports.ModuleModel = ModuleModel;
return ModuleModel;
});
和ModuleCollection.js:
define(['exports', 'use!backbone'], function(exports, Backbone) {
var ModuleCollection = Backbone.RelationalModel.extend({
url: '/api/v1/module/';
model: exports.ModuleModel;
});
exports.ModuleCollection = ModuleCollection;
return ModuleCollection;
});
不久前我遇到了同样的问题,并遵循了Andrew Ferk对他的问题所使用的方法:使用RequireJS的骨干关系子模型。问题的出现是因为您将模型定义为Require模块,这样它们就不存在于全局范围中,而骨干关系可以在全局范围中查找它们。您可以使用addModelScope()为模型定义一个范围,并告诉骨干关系在其中查找模型,而不是使用全局范围(超出了Require的目的)或导出(关系有点棘手)。
//modelStore.js - A scope in which backbone-relational will search for models
//Defined separately so you can access 'modelStore' directly for your models instead of requiring 'app' every time.
define(['app'], function(app) {
app.modelStore = {};
Backbone.Relational.store.addModelScope(app.modelStore);
return app.modelStore;
}
顺便说一句,你应该填补你的主干依赖性,而不需要jQuery和Undercore
//ModuleModel (The ModuleModel module. Nice.)
define(['modelStore', 'backbone', 'backboneRelational'], function(modelStore, Backbone {
modelStore.ModuleModel = Backbone.RelationalModel.extend({
relations: [
{
type: Backbone.HasMany,
key: 'groups',
relatedModel: 'ModuleModel', //Not modelStore.ModuleModel
collectionType: 'ModuleCollection'
}
]
});
return modelStore.ModuleModel;
});
现在有点晚了,但希望它能帮助其他人。