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

本節完

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章