RequireJS + BackboneRelational +自我指涉

时间:2013-06-02 18:47:06

标签: backbone.js requirejs backbone-relational

我一直在尝试按照此处的示例:Creating nested models with backboneJS + backbone-relational + requireJS

最终得到了一些不同的东西(因为我需要Backbone.Collection,而不是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;
});

但是,当我这样做时:

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

我明白了:

TypeError: this.model is undefined

由于在初始化 ModuleCollection之后创建了 Exports.ModuleModel,因此它显而易见。

有关如何实现这种自引用模型的任何提示?

提前致谢!

2 个答案:

答案 0 :(得分:1)

AMD的一个优点是它消除了对全局变量的需求,从而减少了查找对象引用所需的时间。所以,将对象放在全局命名空间中绝对不是AMD:p

原帖中的主要问题似乎源于对RequireJS的误解。我看到三个(可能是四个)问题:

  1. 两个模块都没有声明对另一个模块的引用(它们仅引用Backbone和Backbone-relational)。
  2. exports似乎被用作全局命名空间的替代品 - 事实并非如此。您使用exports为模块创建一个空对象,该模块可立即供其他模块参考 - 但您必须引用它!
  3. relatedModelcollectionType接受对象引用或可通过全局命名空间访问的对象的名称。由于您使用的是AMD,因此不需要定义全局变量,因此需要提供有效的对象引用。
    • collectionType只会指向导入的Collection对象
    • relatedModel有点棘手。因为它是一个自引用,所以它引用的对象在extend()操作完成之前实际上不会存在,所以你必须将其分配延迟到以后。
  4. RequireJS要求每个文件只定义一个模块。我假设上面的代码示例代表两个单独的文件,但如果它们没有,它们应该。
  5. 这应该有效:

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

    希望这会有所帮助......

答案 1 :(得分:0)

好的,我通过在全局范围内公开名称空间来解决它(刚刚删除了var)。

我不知道这是不是AMD的投诉,但至少它看起来并不那么糟糕:

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

如果某人有更好的解决方案,请随时发布!