【问题标题】:Backbone populate Model inside of a Collection骨干在集合内填充模型
【发布时间】:2015-01-21 02:46:13
【问题描述】:

所以这是我的场景:

我有一个充满模型的主干集合。然而,出于性能原因,这些不是“完整”模型。我的“完整”模型非常大(想象每个“完整”模型都有一个同样大的对象的子集合),所以当我从服务器获取集合时,我返回一个“部分”模型数组,其属性是“完整”模型(例如,我只返回子集合的长度而不是完整的子集合),足以在列表视图中向用户显示模型。

现在,当用户从列表中选择一个项目时,我从服务器获取“完整”模型并显示该模型的详细信息视图。我遇到的问题是,现在我有同一个模型的两个版本,集合中的一个“部分”和一个“完整”,手动让它们保持同步并不是正确的做事方式。

我想知道是否存在现有模式(在 Backbone 或 Marionette 中)用于将“部分”模型“填充”到“完整”模型中,同时保留所有相同的引用,以及“减少”当我们不再需要所有额外数据(即用户导航到列表中的另一个项目)时,相同的模型从“完整”模型变为“部分”模型。

我可以完全控制我的应用程序的前端和后端,如果模式需要我更改服务器返回的内容,我可以相应地进行更改。

【问题讨论】:

  • 假设“部分”模型是“完整”模型的子集,是什么阻止您填充集合中的模型,因此您拥有一个以“基本”开头并扩展到“选择时“扩展”?
  • 这正是我想做的,我只是想知道是否有一个很好的模式可以使用,或者我是否必须自己推出。基本上我想知道是否有人已经做过这样的事情并且有任何他们愿意分享的指针。我目前的总体想法是在模型上添加一个填充标志并填充和取消填充函数。
  • 你不能只调用 fetch 来加载集合中的单个模型来加载完整的属性集吗?

标签: backbone.js marionette


【解决方案1】:

您代表的是单个域对象(尽管采用两种不同的形式),因此您应该使用单个 Model 实例来涵盖这两种情况。

一个相当干净的模式:

var MyModel = Backbone.Model.extend({
  // ... existing code...

  inflate: function() {
    return $.ajax({
      // parameters to fetch the full version
    }).then(function(data) {
      // process the response - something like this:
      this.set({
        a: data.a,
        b: data.b
      }, { silent: true })

      this.trigger('inflate')
    })
  },

  deflate: function() {
    this.unset('a', { silent: true });
    this.unset('b', { silent: true });

    // any other cleanup to prevent leaking the large attributes

    this.trigger('deflate')
  }
})

此模式使用自定义inflatedeflate 事件而不是触发change,因为它在语义上更准确。

当然,您可以通过维护一个应该放入/放气的属性名称数组来干掉代码。

【讨论】:

  • 这基本上是我计划做的,但我喜欢你触发自定义inflatedeflate 事件的方式。现在我只需要弄清楚如何并行加载对象集合和单个对象(当用户深层链接到单个项目时),然后确保所有引用都指向相同的Model。本身并不难,只是很尴尬。
【解决方案2】:

就像您的收藏有一个指向“部分”模型的 URL,您的模型应该有一个指向完整版本的 URL:

var Library = Backbone.Collection.extend({
    model: Book,
    url: "/books"
});

var Book = Backbone.Model.extend({
    url: function () {
        return "/books/" + this.get("id");
    }
});

当您单击项目视图时,使用相同的模型,调用 fetch(),并将其传递到详细视图。

var BookView = Backbone.View.extend({

    tagName: "li",

    events: {
        "click .details": "openBook"
    },

    initialize: function() {
        // ...
    },

    openBook: function () {
        this.model.fetch();
        var bookDetailView = new BookDetailView({ model: this.model });
        // Or create the view after successful fetch...
    }

    // ...

});

var BookDetailView = Backbone.View.extend({});

您不会拥有同一模型的两个版本。集合视图中的模型现在将具有所有属性,但它只会显示模板中的内容。

就“人口减少”而言,它似乎没有必要。如果再次单击该项目,您甚至可以检查“完整”模型数据是否可用并丢失额外的获取。如果您真的想删除数据,请继续在模型上创建一个方法来取消设置属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-04
    • 2013-11-08
    • 2012-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多