【问题标题】:Set a Backbone collection model with circular dependencies in requirejs在requirejs中设置一个具有循环依赖的Backbone集合模型
【发布时间】:2015-07-07 14:28:24
【问题描述】:

问题是我在一些 Backbone 模块之间存在循环依赖关系,因此我必须使用“导出”,因为 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)

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

【问题讨论】:

  • 有什么方法可以解决循环依赖而不是尝试解决它?这似乎可能会导致其他挫败感......
  • @rjz 我知道循环依赖通常是一种不好的做法,但是在任何情况下都需要它们,或者你永远不应该有循环依赖?
  • 某处可能存在案例,但它们绝对是代码异味。如果有可能重构您的数据模型以避免它们,它将使模型更清晰和更易于维护(相关:en.wikipedia.org/wiki/Law_of_Demeter
  • 如果我无法解决循环依赖问题,我应该如何解决这个问题?

标签: javascript backbone.js requirejs


【解决方案1】:

从示例中,不清楚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()
    });
  }
});

【讨论】:

    【解决方案2】:

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

    你有一个模型,你有一个收藏。为了使它们都相互依赖+避免循环依赖,您需要第三个“中介”依赖。在 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];
            }
        };
    
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-27
      • 2014-12-16
      • 2012-07-01
      • 1970-01-01
      • 2014-09-22
      • 1970-01-01
      • 2020-10-27
      • 2021-08-15
      相关资源
      最近更新 更多