在requirejs中设置具有循环依赖关系的Backbone集合模型

时间:2015-07-07 14:28:24

标签: javascript backbone.js requirejs

问题是我在某些Backbone模块之间有一个循环依赖,所以我必须使用“exports”作为Requirejs在其文档http://requirejs.org/docs/api.html#circular中指定。因此模型'A'将如下所示:

define(function(require, exports) {
  var B = require('B');
  var A = Backbone.Model.extend({

  });

  exports.model =  A;
});

集合'B'是这样的:

define(function(require, exports) {
  var A = require('A');
  var B = Backbone.Model.extend({
    model: A.model
  });

  exports.model =  B;
});

这里的问题是,当我必须指定集合'B'模型属性时,尚未定义模型'A'。当我尝试使用这样的模型设置集合时,这是我得到的错误:

B.collection.set([{id: 1}, {id: 2}]);

Uncaught TypeError: 'undefined' is not an object (evaluating 'targetModel.prototype') (http://127.0.0.1:9999/bower_components/backbone/backbone.js:689)

关于如何解决这个问题的任何想法?

2 个答案:

答案 0 :(得分:3)

从示例中,B实际上取决于A并不清楚。如果它只是一个模型:集合关系,那么删除模型对其集合的依赖性可能是有意义的。如果完全可以打破循环依赖,我强烈建议你这样做。

如果确实需要反向引用,一个选项可能是将资源移动到同一个模块中并进行一种延迟导出:

define(function() {

  var lazyThings = {
    A: null,
    B: null
  };

  lazyThings.A = Backbone.Model.extend({
    collection: things.B
  });

  lazyThings.B = Backbone.Collection.extend({
    model: A
  });

  return lazyThings;
});

或者,你可以return lazyThings.B然后从原型中访问模型:

require('b', function (B) {
  var A = B.prototype.model; // A
});

最后,可以通过懒惰地调用相应的依赖项来使requirejs工作(即,在解析模块之后):

// B
define(['a'], function (A) {
  return function () {
    return Backbone.Collection.extend({
      model: A()
    });
  }
});

// A
define(['b'], function (B) {
  return function () {
    return Backbone.Model.extend({
      model: B()
    });
  }
});

答案 1 :(得分:0)

以下对我有用,尽量说清楚。

你有一个模特,你有一个集合。为了使它们彼此依赖+避免循环依赖,你需要第3个“中介”依赖。在Backbone中使用模型并轻松查找它所属的集合很方便,反之亦然,但问题当然是它们具有循环依赖性。

所以在我们开始之前:

+model
+collection
__________
= circular

之后:

+model
+collection
+mediator
________
= OK

//收集

define([

        '@allModels',
        '@BaseCollection',
        '@AppDispatcher',
        '@allFluxConstants',
        'app/js/flux/flux-helpers/collectionUpdater'
    ],

    function (allModels, BaseCollection, AppDispatcher, allFluxConstants, collUpdater) {


        var dispatchCallback = function (payload) {
            return true;
        };


        var BaymaxComponentCollection = BaseCollection.extend({


            model: allModels['BaymaxComponent'],

            collectionName:'baymax-component',

            url: '/baymax_component',

            batchURL: '/batch/baymax_component',


            initialize: function (models, opts) {

                this.dispatchToken = AppDispatcher.register(dispatchCallback);


            },

            // collection is sorted by original insertion order.
            comparator: 'order'
        });


        return new BaymaxComponentCollection();
    });

//模型

define([

        '@BaseModel',
        '@ModelCollectionMediator',
        '@AppDispatcher'

    ],

    function ( BaseModel, MCM) {

        var BaymaxComponent = BaseModel.extend({

                idAttribute: 'id',
                urlRoot: '/baymax_component',
                collectionName: 'baymax-component',

                defaults: function () { //prevents copying default attributes to all instances of UserModel
                    return {}
                },

                initialize: function (attributes, opts) {

                    //*** the following line is crucial ***
                    this.collection = MCM.findCollectionByName(this.collectionName);

                },


                validate: function (attr) {

                    return undefined;
                }
            },

            { //class properties

            });

        return BaymaxComponent;
    });

//介

define(function (require) {

    return {
        findCollectionByName: function (name) {
            var allCollections = require('@allCollections');
            return allCollections[name];
        }
    };

});