7

我有点坚持在 emberjs 中实现主细节视图。

我的大多数视图都有一个主视图,它只是一个标题列表。然后,用户可以点击这样的标题,他/她会得到一个带有详细视图的覆盖(有点像典型的新闻站点页面)。

现在,我注意到当 ember 询问主视图的信息时,它会调用 url,例如:/backend/newsitems。但是这些调用可能会变得非常繁重,因为后端会返回所有新闻站点及其所有详细数据的列表。但这感觉不对,因为用户只查看主视图并且还没有请求任何详细信息。

有没有办法让 ember 清楚主视图只需要几个属性,并且对详细信息的请求应该获得该特定项目的额外属性?

举个例子,我的模型如下所示:

App.Newsitem = DS.Model.extend({
  slug: DS.attr('string'),
  type: DS.attr('string'),
  title: DS.attr('string'),
  summary: DS.attr('string'),
  text: DS.attr('string'),
  thumb: DS.attr('string'),
  date: DS.attr('date'),

  mediaitems: DS.hasMany('App.Mediaitem')
});

但我的主视图只需要id type title显示标题列表和该标题旁边的图标。然后,当用户请求一个新闻站点的详细信息时,应该获取所有其他属性。

4

3 回答 3

3

我通过让服务器在有效负载中包含“部分”属性解决了这个问题。如果只是部分响应,“部分”将为真,如果是完整响应,则为假。如果您无法更改服务器 API(因此无法在有效负载中包含“部分”属性),我还将提供一种解决方法。

正如其他人建议的那样,在“详细”路线的模型挂钩中,如果当前加载的模型只是部分模型,则调用模型的 reload() 方法:

App.ItemRoute = Ember.Route.extend({

    model: function (params) {
        return this.store.find('item', params.item_id).then(function (item) {
            if (item.get('partial'))
                return item.reload();
            else
                return item;
        });
    }

});

这解决了部分问题,但是如果您的用户随后导航到主路由,则 Ember Data 将使用服务器响应替换所有字段并清除任何未从服务器返回的属性值。为了克服这个问题,像这样覆盖 store 的 push 方法:

App.ApplicationStore = DS.Store.extend({
    push: function (type, data, _partial) {
        if (data.partial && this.hasRecordForId(type, data.id))
            return this.getById(type, data.id);
        else
            return this._super(type, data, _partial);
    }
});

这可确保您的部分有效负载不会覆盖整个有效负载。

这是一个 jsbin 来演示:http: //jsbin.com/bejop/6/edit

如果您无法在响应中包含“部分”属性,则可以应用与上述相同的逻辑,但在模型中查找将出现在您的详细响应中而不是部分响应中的特定属性。然后当你覆盖 push 方法时,你可以这样做:

    App.Partials = [
        { type: App.Item, propertyName: 'detailed_description' }
    ];

    App.ApplicationStore = DS.Store.extend({
        push: function (type, data, _partial) {

            var that = this;
            var partial = App.Partials.find(function (p) {
                return p.type === that.modelFor(type);
            });

            if (partial && !data[partial.propertyName])
                return this.getById(type, data.id);

            return this._super(type, data, _partial);
        }
    });
于 2014-07-10T17:32:35.373 回答
2

我最近遇到了类似的问题,希望我想出的可以帮助你。

我的 API 有一个/books端点,它返回一个包含多个(但不是全部)字段的对象数组。但是,当我GET /books/:id使用 ID 时,我可以获取有关这本书的所有信息:id

然后,在 Ember 中,我为单个书页设置了以下路线:

App.BookRoute = Ember.Route.extend
  model: (params) ->
    Book.find(params.book_id)

  setupController: (controller, model) ->
    controller.set("model", model)

    unless model.get('full') is true
      model.reload().then ->
        # We now have all the information.
        # Setting `full` to `true` to prevent loading it again.
        model.set('full', true)
    return

因此,当用户只是浏览列表时,模型的字段大部分是空的,但是当她随后进入书籍详细信息视图时,API 被命中,并且额外的书籍数据被插入到同一个模型实例中。

于 2013-08-31T21:52:51.920 回答
2

有没有办法让 ember 清楚主视图只需要几个属性,并且对详细信息的请求应该获得该特定项目的额外属性?

当然可以,但可能不是您所期望的方式。Ember 模型非常轻量级,因此它们与您的后端架构之间无需建立 1-1 的关系。一般来说,我喜欢从 API 端点来考虑 ember-models。在这种情况下,您的 API 公开了 2 组不同的数据,因此最直接的解决方案是创建一个单独的 ember 模型来表示轻量级标题列表。这个模型将有它自己的 api 端点/backend/newsitem_listings

App.NewsitemListing = DS.Model.extend({
  slug: DS.attr('string'),
  type: DS.attr('string'),
  title: DS.attr('string')
});

有了这个,您可以使用App.NewsitemListing.find()App.NewsitemListing.find({query: q})获取部分/所有列表,然后App.Newsitem.find(id)加载单个记录的详细信息。您可能会考虑添加一个关系,例如newsitem: DS.hasOne('App.Newsitem')模型,或者您可以使用 slug 动态生成链接。

于 2013-03-05T13:13:47.340 回答