#3 给路由分配模型

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

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

比如,下面这个路由:

app/router.js

Router.map(function() {
  this.route('favorite-posts');
});

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

app/routes/favorite-posts.js

import 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.js

Router.map(function() {
  this.route('photo', { path: '/photos/:photo_id' });
});
app/routes/photo.js

import 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.js

import 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>

本节完

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值