Ano*_*ous 85 ember.js ember-data
通过阅读文档,您似乎必须(或应该)将模型分配给路径,如下所示:
App.PostRoute = Ember.Route.extend({
model: function() {
return App.Post.find();
}
});
Run Code Online (Sandbox Code Playgroud)
如果我需要在某个路线中使用多个物体怎么办?即帖子,评论和用户?如何告诉路由加载这些?
Mil*_*Joe 117
永远的最后更新:我不能继续更新这个.所以这已被弃用,可能会这样.这是一个更好的,更新的线程EmberJS:如何在同一条路线上加载多个模型?
更新:在我原来的答案中,我说要embedded: true在模型定义中使用.那是不对的.在修订版12中,Ember-Data期望使用后缀(链接)_id为单个记录或_ids集合定义外键.类似于以下内容:
{
id: 1,
title: 'string',
body: 'string string string string...',
author_id: 1,
comment_ids: [1, 2, 3, 6],
tag_ids: [3,4]
}
Run Code Online (Sandbox Code Playgroud)
我已经更新了小提琴,如果有任何变化或者如果我发现此答案中提供的代码存在更多问题,我将再次这样做.
回答相关型号:
对于情况下,你的描述,我将依靠关联模型之间(设置,并只加载embedded: true)Post模型,这条路线,考虑到我可以定义一个DS.hasMany用于关联Comment模型和DS.belongsTo协会User中都Comment和Post车型.像这样的东西:
App.User = DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
email: DS.attr('string'),
posts: DS.hasMany('App.Post'),
comments: DS.hasMany('App.Comment')
});
App.Post = DS.Model.extend({
title: DS.attr('string'),
body: DS.attr('string'),
author: DS.belongsTo('App.User'),
comments: DS.hasMany('App.Comment')
});
App.Comment = DS.Model.extend({
body: DS.attr('string'),
post: DS.belongsTo('App.Post'),
author: DS.belongsTo('App.User')
});
Run Code Online (Sandbox Code Playgroud)
这个定义会产生如下内容:

有了这个定义,每当我find发布帖子时,我都可以访问与该帖子相关的评论集合,以及评论的作者,以及作为帖子作者的用户,因为它们都是嵌入的.路线保持简单:
App.PostsPostRoute = Em.Route.extend({
model: function(params) {
return App.Post.find(params.post_id);
}
});
Run Code Online (Sandbox Code Playgroud)
所以在PostRoute(或者PostsPostRoute你正在使用resource)中,我的模板可以访问控制器content,这是Post模型,所以我可以简单地引用作者author
<script type="text/x-handlebars" data-template-name="posts/post">
<h3>{{title}}</h3>
<div>by {{author.fullName}}</div><hr />
<div>
{{body}}
</div>
{{partial comments}}
</script>
<script type="text/x-handlebars" data-template-name="_comments">
<h5>Comments</h5>
{{#each content.comments}}
<hr />
<span>
{{this.body}}<br />
<small>by {{this.author.fullName}}</small>
</span>
{{/each}}
</script>
Run Code Online (Sandbox Code Playgroud)
(见小提琴)
回答非相关模型:
但是,如果您的场景比您描述的更复杂,并且/或者必须使用(或查询)特定路线的不同模型,我建议您进行此操作Route#setupController.例如:
App.PostsPostRoute = Em.Route.extend({
model: function(params) {
return App.Post.find(params.post_id);
},
// in this sample, "model" is an instance of "Post"
// coming from the model hook above
setupController: function(controller, model) {
controller.set('content', model);
// the "user_id" parameter can come from a global variable for example
// or you can implement in another way. This is generally where you
// setup your controller properties and models, or even other models
// that can be used in your route's template
controller.set('user', App.User.find(window.user_id));
}
});
Run Code Online (Sandbox Code Playgroud)
现在,当我在Post路径中时,我的模板可以访问user控制器中的属性,因为它是在setupController挂钩中设置的:
<script type="text/x-handlebars" data-template-name="posts/post">
<h3>{{title}}</h3>
<div>by {{controller.user.fullName}}</div><hr />
<div>
{{body}}
</div>
{{partial comments}}
</script>
<script type="text/x-handlebars" data-template-name="_comments">
<h5>Comments</h5>
{{#each content.comments}}
<hr />
<span>
{{this.body}}<br />
<small>by {{this.author.fullName}}</small>
</span>
{{/each}}
</script>
Run Code Online (Sandbox Code Playgroud)
(见小提琴)
dar*_*123 49
使用Em.Object封装多个模型是获取所有数据的好方法model.但它无法确保在视图渲染后准备好所有数据.
另一种选择是使用Em.RSVP.hash.它将多个承诺结合在一起并返回新的承诺.在所有承诺得到解决后解决的新承诺.并且setupController在承诺得到解决或拒绝之前不会被调用.
App.PostRoute = Em.Route.extend({
model: function(params) {
return Em.RSVP.hash({
post: // promise to get post
comments: // promise to get comments,
user: // promise to get user
});
},
setupController: function(controller, model) {
// You can use model.post to get post, etc
// Since the model is a plain object you can just use setProperties
controller.setProperties(model);
}
});
Run Code Online (Sandbox Code Playgroud)
这样,您可以在视图渲染之前获得所有模型.并且使用Em.Object没有这个优势.
另一个优点是你可以结合承诺和非承诺.像这样:
Em.RSVP.hash({
post: // non-promise object
user: // promise object
});
Run Code Online (Sandbox Code Playgroud)
检查这一点以了解更多信息Em.RSVP:https://github.com/tildeio/rsvp.js
但如果您的路线有动态段,请不要使用Em.Object或Em.RSVP解决方案
主要问题是link-to.如果通过单击link-to模型生成的链接更改URL ,则模型将直接传递到该路径.在这种情况下,model钩子不会被调用,在setupController你得到模型link-to给你.
一个例子是这样的:
路线代码:
App.Router.map(function() {
this.route('/post/:post_id');
});
App.PostRoute = Em.Route.extend({
model: function(params) {
return Em.RSVP.hash({
post: App.Post.find(params.post_id),
user: // use whatever to get user object
});
},
setupController: function(controller, model) {
// Guess what the model is in this case?
console.log(model);
}
});
Run Code Online (Sandbox Code Playgroud)
和link-to代码,帖子是一个模型:
{{#link-to "post" post}}Some post{{/link-to}}
Run Code Online (Sandbox Code Playgroud)
事情在这里变得有趣.当您使用url /post/1访问该页面时,将model调用该钩子,并setupController在promise解析时获取普通对象.
但是如果你通过点击link-to链接访问该页面,它会将post模型传递给PostRoute,并且路由将忽略model钩子.在这种情况下setupController会获得post模型,当然你无法获得用户.
因此,请确保不要在具有动态段的路径中使用它们.
小智 13
有一段时间我正在使用Em.RSVP.hash,但我遇到的问题是我不希望我的视图等到所有模型在渲染之前加载.然而,由于Novelys的人们使用了Ember.PromiseProxyMixin,我找到了一个很棒的(但相对未知的)解决方案:
假设您有一个具有三个不同视觉部分的视图.这些部分中的每一部分都应该有自己的模型.支持视图顶部"splash"内容的模型很小,并且会快速加载,因此您可以正常加载该模型:
创建路线main-page.js:
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.find('main-stuff');
}
});
Run Code Online (Sandbox Code Playgroud)
然后,您可以创建相应的Handlebars模板main-page.hbs:
<h1>My awesome page!</h1>
<ul>
{{#each thing in model}}
<li>{{thing.name}} is really cool.</li>
{{/each}}
</ul>
<section>
<h1>Reasons I Love Cheese</h1>
</section>
<section>
<h1>Reasons I Hate Cheese</h1>
</section>
Run Code Online (Sandbox Code Playgroud)
所以,让我们在你的模板中说你想要有关于你与奶酪的爱/恨关系的单独部分,每个(由于某种原因)由它自己的模型支持.每个模型中都有许多记录,其中包含与每个原因相关的详细信息,但是您希望顶部的内容能够快速呈现.这是{{render}}助手进来的地方.您可以更新模板:
<h1>My awesome page!</h1>
<ul>
{{#each thing in model}}
<li>{{thing.name}} is really cool.</li>
{{/each}}
</ul>
<section>
<h1>Reasons I Love Cheese</h1>
{{render 'love-cheese'}}
</section>
<section>
<h1>Reasons I Hate Cheese</h1>
{{render 'hate-cheese'}}
</section>
Run Code Online (Sandbox Code Playgroud)
现在,您需要为每个创建控制器和模板.因为它们在这个例子中实际上是相同的,所以我只使用一个.
创建一个名为控制器love-cheese.js:
import Ember from 'ember';
export default Ember.ObjectController.extend(Ember.PromiseProxyMixin, {
init: function() {
this._super();
var promise = this.store.find('love-cheese');
if (promise) {
return this.set('promise', promise);
}
}
});
Run Code Online (Sandbox Code Playgroud)
您会注意到我们正在使用PromiseProxyMixin此处,这使控制器可以识别承诺.初始化控制器时,我们指出承诺应该love-cheese通过Ember Data 加载模型.您需要在控制器的promise属性上设置此属性.
现在,创建一个名为的模板love-cheese.hbs:
{{#if isPending}}
<p>Loading...</p>
{{else}}
{{#each item in promise._result }}
<p>{{item.reason}}</p>
{{/each}}
{{/if}}
Run Code Online (Sandbox Code Playgroud)
在您的模板中,您将能够根据承诺状态呈现不同的内容.当您的页面最初加载时,将显示"我爱奶酪的原因"部分Loading....加载承诺后,它将呈现与模型的每条记录关联的所有原因.
每个部分将独立加载,不会阻止主要内容立即呈现.
这是一个简单的例子,但我希望其他人发现它和我一样有用.
如果您希望对许多内容行执行类似操作,您可能会发现上面的Novelys示例更具相关性.如果没有,上述应该适合你.
这可能不是最佳实践和天真的方法,但从概念上说明了如何在一条中心路线上使用多种模型:
App.PostRoute = Ember.Route.extend({
model: function() {
var multimodel = Ember.Object.create(
{
posts: App.Post.find(),
comments: App.Comments.find(),
whatever: App.WhatEver.find()
});
return multiModel;
},
setupController: function(controller, model) {
// now you have here model.posts, model.comments, etc.
// as promises, so you can do stuff like
controller.set('contentA', model.posts);
controller.set('contentB', model.comments);
// or ...
this.controllerFor('whatEver').set('content', model.whatever);
}
});
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你
| 归档时间: |
|
| 查看次数: |
29635 次 |
| 最近记录: |