使用backboneJS + backbone-relational + requireJS创建嵌套模型

时间:2012-04-01 07:33:49

标签: backbone.js requirejs backbone-relational

我是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)

你能指出我正确的方向吗?

4 个答案:

答案 0 :(得分:4)

这看起来像是一个范围问题。在初始化ModuleModel期间,它想要与自己创建一个hasMany关系,但它找不到自己,它会让你感到悲伤:

http://jsfiddle.net/yNLbq

一旦从当前范围可以访问该对象,就会开始解决问题:

http://jsfiddle.net/jDw5e

一种可能的解决方案是为模型和集合提供自己的命名空间,这可以从当前范围到达。

希望这有帮助。

答案 1 :(得分:3)

我从这里遇到了这个问题: RequireJS + BackboneRelational + Self-Referential。他似乎从这个帖子中继承了他的一些问题,所以我想我可能会增加我的一角钱。

首先,由于您使用的是RequireJS,因此没有全局变量。您不能简单地提供对象的名称,您需要提供relatedModelcollectionType的实际对象引用。

您最棘手的问题是,ModuleModel的{​​{1}}实际上是relatedModel本身,当您将其分配给ModuleModel时将不会定义(使用AMD模型) )。您必须推迟分配,直到分配relatedModel为止。

最后,您需要解决循环引用。 dokkaebi在建议使用ModuleModel时走在正确的轨道上,但他的实施实际上误用了exports。导出时,按照他的建议将对象直接附加到exports,但是当您导入它时,您需要引用该模块以使用它,而不是exports

这应该有效:

<强> ModuleModel.js

exports

<强> ModuleCollection.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;
});

<强> Main.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;
});

答案 2 :(得分:2)

来自backbone-relational.js v0.5.0(第375行)的评论:
//'exports'应该是全局对象,如果以字符串形式给出,可以找到'relatedModel'。

如果在define调用中需要特殊的“exports”值作为依赖项,然后在返回之前将模块放在exports对象上,则可以将该模块作为字符串或导出成员引用。 / p> 在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;
});

答案 3 :(得分:2)

我回过头来遇到了同样的问题,然后按照Andrew Ferk用来提出问题的方法:Backbone-relational submodels with RequireJS。之所以出现这个问题,是因为您将模型定义为需求模块,因此它们不会存在于全局范围内,而骨干关系可以在其中查找它们。您可以使用addModelScope()来定义模型的范围,并告诉骨干关系在其中查找模型,而不是使用全局范围(超出Require的目的)或导出(对关系有点棘手)。 / p>

//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;
}

顺便说一句,你应该使用Backbone依赖,而不需要jQuery和Underscore。

//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;
});

现在有点迟到了,但希望它有助于其他人。