RequireJS + BackboneRelational + Self-Referential

十年热恋 提交于 2019-12-08 12:25:15

问题


I've been trying to follow the example here: Creating nested models with backboneJS + backbone-relational + requireJS

And ended up having something different (since I need a Backbone.Collection, not a Backbone.RelationalModel):

define(['exports', 'backbone', 'backbone.relational'], function (Exports, Backbone) {
    var ModuleModel = Backbone.RelationalModel.extend({
        relations : [{
                        type : Backbone.HasMany,
                        key : "children",
                        relatedModel : 'ModuleModel',
                        collectionType : 'ModuleCollection'
                     }] 
    });
    Exports.ModuleModel = ModuleModel;
    return ModuleModel;
});

define(['exports', 'backbone'], function(Exports, Backbone) {
    var ModuleCollection = Backbone.Collection.extend({
        model : Exports.ModuleModel,
    });
    Exports.ModuleCollection = ModuleCollection;
    return ModuleCollection;
});

But, when I do:

var modules = new ModuleCollection();
modules.fetch();

I get:

TypeError: this.model is undefined

And it's kind of obvious since Exports.ModuleModel is created after ModuleCollection has been initialized.

Any hints on how to achieve this self-referential model?

Thanks in advance!


回答1:


One of the advantages of AMD is that it eliminates the need for global variables, thereby reducing the time needed to lookup object references. So yea, putting objects in the global namespace most definitely is not AMD :p

The chief problem in your original post appears to stem from a misunderstanding of RequireJS. I see three (maybe four) problems:

  1. Neither module declares a reference to the other (they only reference Backbone and Backbone-relational).
  2. exports appears to be used as a substitute for the global namespace - it isn't. You use exports to create an empty object for the module that is available immediately for reference by other modules - but you have to reference it!
  3. relatedModel and collectionType accept either object references or the names of objects accessible through global namespace. Since you're using AMD you're not defining globals, therefore you need to provide valid object references.
    • collectionType will simply point to the imported Collection object
    • relatedModel is a bit trickier. Since it's a self reference, the object it's referencing won't actually exist until the extend() operation completes, so you have to delay it's assignment until later.
  4. RequireJS requires that each file define exactly one module. I assume that the code samples above represent two separate files, but in case they don't, they should.

This should work:

ModuleModel.js:

define(['exports', 'ModuleCollection'], function (exports, Module) {
    'use strict';

    var Model = Backbone.RelationalModel.extend({
        relations : [{
            type : Backbone.HasMany,
            key : 'children',
            // `Model` undefined at this point in time, so this line is useless:
            relatedModel : Model,
            // `Collection` is attached to the imported `Module` object:
            collectionType : Module.Collection
        }]
    });

    // Now that `Model` is defined, we can supply a valid object reference:
    Model.prototype.relations[0].relatedModel = Model;

    // Attach `Model` to `exports` so an obj ref can be obtained elsewhere
    exports.Model = Model;
});

ModuleCollection.js

define(['exports', 'ModuleModel'], function(exports, Module) {
    'use strict';

    var Collection = Backbone.Collection.extend({
        // `Model` is attached to the imported `Module` object
        model : Module.Model,
        url: 'data.php' // <-- or wherever
    });

    // Attach `Collection` to `exports` so an obj ref can be obtained elsewhere
    exports.Collection = Collection;
});

Main.js

define(['ModuleCollection'], function(Module) {
    'use strict';

    var modules = new Module.Collection();
    modules.fetch();

});

Hope this helps...




回答2:


Ok, I solved it by exposing the namespaces in the global scope (just removed var).

I don't know if this is AMD complaint, but at least it doesn't look that bad:

define(['backbone', 'backbone.relational'], function (Backbone) {
    ModuleModel = Backbone.RelationalModel.extend({
        relations : [{
                        type : Backbone.HasMany,
                        key : "children",
                        relatedModel : 'ModuleModel',
                        collectionType : 'ModuleCollection'
                     }] 
    });
    return ModuleModel;
});

define(['backbone', 'models/module'], function(Backbone, ModuleModel) {
    ModuleCollection = Backbone.Collection.extend({
        model : ModuleModel,
    });
    return ModuleCollection;
});

If someone has a better solution, feel free to post it!



来源:https://stackoverflow.com/questions/16886091/requirejs-backbonerelational-self-referential

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!