#3 给路由分配模型

来源:互联网 发布:feeling软件 编辑:程序博客网 时间:2024/06/14 04:48

英文模板:https://guides.emberjs.com/v2.13.0/routing/specifying-a-routes-model/

通常,你可能会需要通过模板来展示从model中获得的数据。读取正确的模型数据是路由的职责之一。

比如,下面这个路由:

app/router.jsRouter.map(function() {  this.route('favorite-posts');});

为了从favorite-posts路由中读取数据,你需要通过model()钩子函数来达到目的:

app/routes/favorite-posts.jsimport Ember from 'ember';export default Ember.Route.extend({  model() {    return this.get('store').query('post', { favorite: true });  }});

通常,model()钩子会返回Ember Data 记录,但是它也可以返回promise对象(Ember Data记录也是promise对象),普通的javascript对象或数组。Ember会一直等到数据读取完成后(即promise被resolved后)才会渲染模型。

接着,路由会将model()钩子的返回值绑定到其controller的model属性上。然后你就可以在模板中通过controller的model属性来展示数据了。

app/templates/favorite-posts.hbs<h1>Favorite Posts</h1>{{#each model as |post|}}  <p>{{post.body}}</p>{{/each}}

动态模型

一些路由总是显示固定的模型。比如,/photos路由总是固定显示你应用中可用的相片的列表。而且当用户离开这个路由,并且再次访问它时,这个被展示的模型并不会变化。

然而,你肯定会需要这样一个路由:它所展示的模型会根据用户的交互做出调整。你可以想象一个你接触过的可以浏览相片的web app。/photos路由会将照片列表作为模型来渲染,这个画面不变。但是当用户点击一个照片的时候,我们想要通过显示单独照片的模板来展示模型数据。并且如果用户后退,然后再次点击一个不同的照片后,我们就再次展示显示单独照片的模板,但是这次的模型数据不同。

在这种情况下,我们就需要在URL中包含一些数据,这些数据不仅决定要显示的模板,还要决定读取的模型。

在Ember中,这些都可以通过在路由中定义动态段来完成。

一旦你实用动态段来定义路由,那么Ember 就会将帮你把动态段对应的值从URL中提取出来,并且将它做为第一个参数传给 model()钩子:

app/router.jsRouter.map(function() {  this.route('photo', { path: '/photos/:photo_id' });});
app/routes/photo.jsimport Ember from 'ember';export default Ember.Route.extend({  model(params) {    return this.get('store').findRecord('photo', params.photo_id);  }});

在带有动态段的路由的model()钩子中,你需要在模型中带一个ID,路由模板需要它来进行渲染。在上面例子中,我们将照片id (params.photo_id) 作为参数传入Ember Data的findRecord()中。

【注】:带有动态段的路由会在当你通过URL访问的时候调用model()钩子。但是,如果你通过transition(使用link-to的时候),并且提供了model的上下文(link-to的第二个参数),那么model()钩子不会执行。再但是,如果你传的参数是一个标识符(比如id),那么model()会执行

例子,通过transition行为访问phote路由将不会触发model()钩子,因为一个model对象被传入link-to助手:

app/templates/photos.hbs<h1>Photos</h1>{{#each model as |photo|}}  <p>    {{#link-to 'photo' photo}}      <img src="{{photo.thumbnailUrl}}" alt="{{photo.title}}" />    {{/link-to}}  </p>{{/each}}

不过你用这种方式来transition会触发model()钩子(因为link-to收到的是标识符):

app/templates/photos.hbs<h1>Photos</h1>{{#each model as |photo|}}  <p>    {{#link-to 'photo' photo.id}}      <img src="{{photo.thumbnailUrl}}" alt="{{photo.title}}" />    {{/link-to}}  </p>{{/each}}

不带动态段的路由将总是触发model()。

多模型

通过RSVP.hash可以一次性返回多个模型。RSVP.hash接受返回promise对象的参数,并且当所有的promise被resolved后,RSVP.hash才会被resolved。例:

app/routes/songs.jsimport Ember from 'ember';import RSVP from 'rsvp';export default Ember.Route.extend({  model() {    return RSVP.hash({      songs: this.get('store').findAll('song'),      albums: this.get('store').findAll('album')    });  }});

在songs模板中,我们指定了2个模型,然后可以通过{{#each}}助手分别将song模型和album模型展示出来:

app/templates/songs.hbs<h1>Playlist</h1><ul>  {{#each model.songs as |song|}}    <li>{{song.name}} by {{song.artist}}</li>  {{/each}}</ul><h1>Albums</h1><ul>  {{#each model.albums as |album|}}    <li>{{album.title}} by {{album.artist}}</li>  {{/each}}</ul>

本节完