【问题标题】:Creating nested models with backboneJS + backbone-relational + requireJS使用主干JS + 主干关系 + requireJS 创建嵌套模型
【发布时间】:2012-04-01 07:33:48
【问题描述】:

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

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

【问题讨论】:

标签: backbone.js requirejs backbone-relational


【解决方案1】:

这看起来像是一个范围界定问题。在ModuleModel 的初始化过程中,它想与自己创建一个hasMany 关系,但它找不到自己,它会以所述错误的形式给你带来悲伤:

http://jsfiddle.net/yNLbq

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

http://jsfiddle.net/jDw5e

一种可能的解决方案是为模型和集合提供一个可以从当前范围访问的名称空间。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

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

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

    您最棘手的问题是 ModuleModelrelatedModel 实际上是 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);
          });
        });
    
    });
    

    【讨论】:

      【解决方案3】:

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

      如果您需要特殊的 '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;
      });
      

      【讨论】:

      • exports 不是你定义的;它被要求特殊处理。 Requirejs 创建一个字典并将其传递给任何需要“导出”的定义,以便您可以在定义调用之间共享值。你不需要创建一个文件,也不需要做任何特别的事情——只需使用神奇的名字'exports'作为你的依赖项之一。
      • 请问我应该实例化哪个模块?两者或只有一个,如果只有一个,ModuleCollection 和 ModuleModel 之间的哪个?
      • 使用我发布的代码,ModuleModel 和 ModuleCollection 都应该按预期工作。在您的代码的其他地方,您可能会执行require(['ModuleCollection', 'ModuleModel'], function(ModuleCollection, ModuleModel) { myModules = new ModuleCollection(); myModel = new ModuleModel({ /* some values */ }); myModules.add(myModel); } 之类的操作。了解您正在尝试做什么可能会有所帮助 - 如果这不能按预期工作,您可以在此处打开一个新问题并链接到它。
      【解决方案4】:

      前段时间我遇到了同样的问题,并采用了 Andrew Ferk 用于他的问题的方法:Backbone-relational submodels with 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;
      }
      

      顺便说一句,您应该填充您的 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;
      });
      

      现在有点晚了,但希望它可以帮助其他人。

      【讨论】:

        猜你喜欢
        • 2014-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-15
        相关资源
        最近更新 更多