英文模板: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>
本節完