Ember.js 在emberjs中使用更详细的数据动态填充模型

Ember.js 在emberjs中使用更详细的数据动态填充模型,ember.js,ember-data,Ember.js,Ember Data,我对在emberjs中实现主细节视图有点纠结 我的大多数视图都有一个主视图,它只是一个标题列表。然后,用户可以单击这样的标题,他/她会得到一个带有细节视图的覆盖图(有点像一个典型的新闻条目页面) 现在,我注意到,当ember询问主视图的信息时,它会调用URL,如:/backend/newitems。但是这些调用可能会非常繁重,因为后端会返回一个包含所有新闻项及其详细数据的列表。但这感觉不对,因为用户只查看主视图,还没有请求任何详细信息 有没有办法让ember明白主视图只需要几个属性,而详细信息请

我对在emberjs中实现主细节视图有点纠结

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

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

有没有办法让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')
});
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);
    }
});
    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);
        }
    });
但是我的主视图只需要
id
类型
标题
即可显示标题列表和标题旁边的图标。 然后,当用户请求一个新闻项的详细信息时,应获取所有其他属性

有没有办法让ember明白主视图只需要几个属性,而详细信息请求应该获得该特定项的额外属性

当然可以,但可能不是你期望的那样。Ember模型实际上是轻量级的,因此它们与后端模式之间不需要1-1关系。总的来说,我喜欢从API端点的角度考虑ember模型。在本例中,API公开了两组不同的数据,因此最简单的解决方案是创建一个单独的ember模型来表示轻量级的标题列表。此模型将在
/backend/newsitem\u列表中有自己的api端点

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.newsitems.find(id)
加载单个记录的详细信息。你可以考虑添加一个关系,例如:代码> NeStime:DS .HasOne(App.NexSeTM)模型,或者你可以使用SLUG来生成链接。

< P>最近我也遇到了类似的问题,我希望我所提出的可以帮助你。 我的API有一个
/books
端点,它返回一个包含多个(但不是全部)字段的对象数组。但是,当我
GET/books/:id
时,我可以通过id
:id
查看该书的所有信息

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

App.BookRoute=Ember.Route.extend
型号:(参数)->
Book.find(参数Book\u id)
设置控制器:(控制器,型号)->
controller.set(“model”,model)
除非model.get('full')为真
model.reload()。然后->
#我们现在掌握了所有信息。
#将“full”设置为“true”,以防止再次加载。
model.set('full',true)
返回

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

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

正如其他人所建议的,如果当前加载的模型只是部分模型,则在“detail”路由的模型钩子中调用模型的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;
        });
    }

});
这解决了部分问题,但如果用户随后导航到主路由,则余烬数据将用服务器响应替换所有字段,并清除所有未从服务器返回的属性值。要克服此问题,请如下重写存储的推送方法:

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')
});
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);
    }
});
    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);
        }
    });
这确保了部分负载不会覆盖完整负载

这里有一个jsbin来演示:

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

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')
});
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);
    }
});
    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);
        }
    });

虽然这是我能在Ember中找到的最好的方法,但我现在最讨厌的是,当你更新(或删除)一个“NewsItem”时,相应的“NewsItemList”显然不知道要更新。这意味着我必须做很多“更新两者”来保持同步,这与ember-way相反。对于发现这一点的读者来说,如果你走这条路,另一件要注意的事情是你的linkTo助手不再工作,因为你正在传递一个不同类型的模型。如果linkTo接受的是一个ID而不是完整的对象,那就太好了,也许有人能想出如何做到这一点?是的,这是一个很好的观点-可能有一个解决办法,但必须考虑一下。建议打开一个新的SO问题,看看是否有其他人有解决方案……有传言说,ember data的其他分支正在努力解决这个问题,甚至可能是针对1.0版本。我认为现在最好的办法是,去掉那些挑逗性的东西,去掉所有这些非余烬方式的代码,让它们迎头赶上。是的,我也听到过同样的话。不过,似乎应该可以使用linkTo来指定一个ID,而不是一个完整的对象。实际上,我对这种方法有一个问题,因为当列表视图的API响应在细节响应之后出现时,成员数据会覆盖所有字段(并且您的附加字段被设置为
未定义的
):在列表视图路径中,您可以编写如下内容: