什么是用于管理模型实例的良好Backbone模式?

时间:2013-08-06 09:36:09

标签: backbone.js

我正在尝试通过避免任何可能的请求来最小化服务器调用。

让我们说,为了举个例子,我有一个属于用户并分配了标签的火柴盒集合,然后还有一组标签和一组用户作为其他页面的一部分。获取火柴盒会检索用户和标记信息,以便我可以使用一个请求实例化所有必需的模型,访问“标记”和“用户”页面可以检索类似的集合(只有它们只处理各自的模型)。

我的问题:如果火柴盒是一个页面,而标签和用户是另外两个页面,那么确保只有一个模型可以为任何给定实体实例化的好方法,即。如果我进入用户或标签并编辑与火柴盒相关联的条目,则火柴盒条目应该具有相同的条目,允许其监听并对更新作出反应,而不需要在返回示例中的火柴盒页面时发送请求。 / p>

我已经查看了Backbone.relational,但它似乎没有做我需要的东西,而宁愿不让自己陷入框架。所以涉及模式的解决方案更可取。

3 个答案:

答案 0 :(得分:1)

使用http://pathable.github.io/supermodel/结束,使用覆盖集合上model属性的模式,使用自定义函数调用特殊的Model.create,该函数本身返回一个现有的(使用新值更新)如果必要的话)所述模型的实例。 Model.create调用必须在代码中的其他地方用于唯一模型。

所以基本上每个模型都有一个all()方法,它是id的所有实例的集合。无论何时添加模型,它都会对集合进行检查,并返回现有对象(如果存在);用于实例化副本的数据用于更新现有对象,确保数据不会过时(这对我想要的唯一性有好处)。

最干净的方法似乎是将模型函数包装到一个函数中,该函数返回它以便更清楚地使用;然后为每个需要有独特模型的集合在函数中包装所述模型。我现在想出了这个:

app.single = function (modelPrototype) {
    return function (attrs, options) {
        return modelPrototype.create(attrs, options);
    };
};

app只有一个范围全局,与特定命名空间绑定)

所以在集合中代替,

model: app.Model

然后我会用

model: app.single(app.Model),

每当我更新应用程序的一个部分中的条目时,更改将逐渐渗透到每个其他集合/模型,因为如果从用户的角度来看它是相同的实例,那么它也是代码中的相同实例。

这是我通过代码和文档阅读模式所能告诉的全部内容。这足以供我自己使用。

我怀疑如果你正在缓存渲染,这个解决方案仍然会有一些问题,但我没有找到它的用途(更喜欢重新渲染,只要我可以避免处理各种工件)所以这对我有好处

不幸的是,代码库似乎被部分放弃了,所以虽然它适用于Backbone 1.0.0(就独特模型而言),我可能需要在未来的项目中重新创建/分叉模式。

答案 1 :(得分:0)

我认为你应该三思而后行,以这种方式嵌套你的模型和集合,特别是如果它主要是为了简化应用程序的引导。相反,尽量使用id来模拟模型之间的相互引用。如果您现在以某种方式构建模型/集合树,那么您遇到的这个设计问题很可能只是众多问题中的第一个,但后来发现它太不灵活了。

话虽如此,如果您需要的是引用其他模型/集合的模型能够引用相同的模型/集合实例,那么在引导期间简单地实例化它们并将它们传递到它们各自的父模型就足够了。您可以在一个请求中加载一些引导数据,或者最好在HTML中内联该数据:

<script>
var bs_data = {
    users : [
        ...
    ],
    tags : [
        ...
    ],
    matchboxes : [
        ...
    ]
};
</script>

然后使用bootstap数据实例化相应的模型或集合。

var matchboxes = new Matchboxes();
matchboxes.set(bs_data.matchboxes);

var users = new Users({matchboxes:matchboxes});
users.set(bs_data.users);

引导数据来自同一个后端,因此您的模型和集合已经同步,无需获取任何内容。

至于设计模式;将依赖关系作为构造函数参数传递实际上是依赖注入模式,尽管存在更多自动化解决方案。

答案 2 :(得分:0)

要确保只实例化一个模型,并且在使用它的其他元素之间共享它,能够在任何元素对其进行更改时进行侦听和更新,您可以使用Singleton模式。您可以阅读更多相关信息here

如果使用Requirejs,如果始终返回实例化的模型,则可以获得相同的效果。例如:

// the shared model
define([
  'jquery',
  'underscore',
  'backbone'
], function ($, _, Backbone) {
  'use strict';

  var Model = Backbone.Model.extend({

    // ...

  });
  // return instantiated, so we'll get the same object back whenever we use this model (singleton)
  return new Model();

});

// a view using the model
define([
  'jquery',
  'underscore',
  'backbone',
  'model'
], function ($, _, Backbone, modelInstance) {
  'use strict';

  var View = Backbone.View.extend({
    initialize: function () {
        // listen to what other elements do
        this.listenTo(modelInstance, 'eventFromOtherElement', this.doSomething);
        // when this element does something, other elements should be listening to that event
        modelInstance.trigger('thisViewEvent');
    },
    doSomething: function () {
        // ...
    }
  });
  return View;
});