Ember 指定與路由關聯(lián)的模型

2018-01-06 17:47 更新

路由其中一個很重要的職責就是加載適合的model,初始化數(shù)據(jù),然后在模板上顯示數(shù)據(jù)。

1,普通model關聯(lián)

//  app/router.js


//  ……


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


export default Router;

對于posts這個路由如果要加載名為postmodel要怎么做呢?代碼實現(xiàn)很簡單,其實在前面的代碼也已經(jīng)寫過了。你只需要重寫model回調(diào),在回調(diào)中返回獲取到的model即可。

//  app/routes/posts.js


import Ember from 'ember';


export default Ember.Route.extend({
    model: function() {
        // return Ember.$.getJSON('https://api.github.com/repos/emberjs/ember.js/pulls');
        // 加載post(是一個model)
        return this.store.query('post');
    }
});

model回調(diào)可以返回一個Ember Data記錄,或者返回任何的promise對象(Ember Data也是promise對象),又或者是返回一個簡單的javascript對象、數(shù)組都可以。但是需要等待數(shù)據(jù)加載完成才會渲染模板,所以如果你是使用Ember.$.getJSON('https://api.github.com/repos/emberjs/ember.js/pulls');獲取遠程數(shù)據(jù)頁面上會有一段時間是空白的,其實就是在加載數(shù)據(jù),不過這樣的用戶體驗并不好,不過你也不需要擔心這個問題,Ember已經(jīng)提供了解決辦法。還記得上一篇的截圖的路由表嗎?是不是每個路由都有一個xxx_loading路由,這個路由就是在數(shù)據(jù)加載的時候執(zhí)行的,有關xxx_loading更多詳細的信息在后面的博文介紹。

2,動態(tài)model

一個route有時候只加載同一個model,比如路由/photos就通常是加載模型photo。如果用戶離開或者是重新進入這個路由模型也不會改變。 然而,有些情況下路由所加載的model是變化的。比如在一個圖片展示的APP中,路由/photos會加載一個photo模型集合并渲染到模板photos上。當用戶點擊其中一幅圖片的時候路由只加載被點擊的model數(shù)據(jù),當用戶點擊另外一張圖片的時候加載的又是另外一個model并且渲染到模板上,而且這兩次加載的model數(shù)據(jù)是不一樣的。

在這種情形下,訪問的URL就包含了很重要的信息,包括路由和模型。

在Ember應用中可以通過定義動態(tài)段實現(xiàn)加載不同的模型。有關動態(tài)段的知識在前面的Ember.js 入門指南之十三{{link-to}} 助手Ember.js 入門指南之二十路由定義已經(jīng)做過介紹。

一旦在路由中定義了動態(tài)段Ember就會從URL中提取動態(tài)段的值作為model回調(diào)的第一個參數(shù)。

//  app/router.js
// ……


Router.map(function() {
    this.route('posts', function() {
        this.route('post', { path: '/:post_id'});
    }); 
});


export default Router;

這段代碼定義了一個動態(tài)段:post_id,記得動態(tài)段是以:”開頭。然后在model回調(diào)中使用動態(tài)段獲取數(shù)據(jù)。

//  app/routes/posts.js


import Ember from 'ember';
export default Ember.Route.extend({
    model: function(params) {
        return this.store.findRecord('post', params.post_id);
    }
});

可以看到在model回調(diào)中也是使用在路由中定義的動態(tài)段,并把這個動態(tài)段作為參數(shù)傳遞給Ember的方法findRecord,Ember會把URL對應位置上的數(shù)據(jù)解析到這個動態(tài)段上。

注意:在model中的動態(tài)段只在通過URL訪問的時候才會被解析。如果你是通過其他方式(比如使用link-to進入路由)轉(zhuǎn)入路由的,那么路由中model回調(diào)方法里的動態(tài)不會被解析,所請求的數(shù)據(jù)會直接從上下文中獲?。憧梢园焉舷挛南胂蟪蒭mber的緩存)。下面的代碼將為你演示這個說法:

1,首先創(chuàng)建一個model:ember g model post

import DS from 'ember-data';


export default DS.Model.extend({
    title: DS.attr('string'),
    body: DS.attr('string'),
    timestamp: DS.attr('number')
});

定義了3個屬性,id屬性不需要顯示定義,ember會默認加上。

2,在posts下增加一個子路由

Router.map(function() {
    this.route('posts', function() {
        this.route('post', { path: '/:post_id'});
    }); 
});

然后用Ember CLI命令(ember g route posts/post)在創(chuàng)建路由post,同時也會自動創(chuàng)建出子模板post.hbs。創(chuàng)建完成之后會得到如下兩個文件:

1.app/routes/posts/post.js
2.app/templates/posts/post.hbs

修改路由posts.js,在model回調(diào)中返回設定的數(shù)據(jù)。

//  app/routes/posts.js


import Ember from 'ember';


export default Ember.Route.extend({
    model: function(params) {
        return [
            {
                "id":"-JzySrmbivaSSFG6WwOk",
                "body" : "testsssss",
                "timestamp" : 1443083287846,
                "title" : "test"
            },
            {
                "id":"-JzyT-VLEWdF6zY3CefO",
                "body" : "33333333",
                "timestamp" : 1443083323541,
                "title" : "test33333"
            },
            {
                "id":"-JzyUqbJcT0ct14OizMo" ,
                "body" : "body.....",
                "timestamp" : 1443083808036,
                "title" : "title1231232132"
            }
        ];
    }
});

修改posts.hbs,遍歷顯示所有的數(shù)據(jù)。

<ul>
    {{#each model as |item|}}
        <li>
            {{#link-to 'posts.post' item}}{{item.title}}{{/link-to}}
        </li>   
    {{/each}}
</ul>


<hr>
{{outlet}}

修改子路由post.js,使得子路由根據(jù)動態(tài)段返回匹配的數(shù)據(jù)。

// app/routes/posts/post.js


import Ember from 'ember';


export default Ember.Route.extend({
    model: function(params) {
        console.log('params = ' + params.post_id);
        return this.store.findRecord('post', params.post_id);
    }
});

注意打印信息語句console.log();,然后接著修改子模板post.hbs。





<h2>{{model.title}}</h2>
<p>{{model.body}}</p>

到此,全部所需的測試數(shù)據(jù)和代碼已經(jīng)編寫完畢。下面執(zhí)行http://localhost:4200/posts,可以看到界面上顯示了所有在路由posts的model回調(diào)中設置的測試數(shù)據(jù)。查看頁面的HTML代碼:

html

可以看到每個連接的動態(tài)段都被解析成了數(shù)據(jù)的id屬性值。 注意:隨便點擊任意一個,注意看瀏覽器控制臺打印的信息。 我點擊了以第一個連接,瀏覽器的URL變?yōu)?/p>

html

看瀏覽器的控制臺是不是并沒有打印出params = -JzySrmbivaSSFG6WwOk,在點擊其他的連接結果也是一樣的,瀏覽器控制臺沒有打印出任何信息。

下面我我們直接在瀏覽器地址欄上輸入:http://localhost:4200/posts/-JzyUqbJcT0ct14OizMo然后按enter執(zhí)行,注意看瀏覽器控制臺打印的信息?。?!此時打印了params = -JzyUqbJcT0ct14OizMo,你可以用同樣的方式執(zhí)行另外兩個鏈接的地址。同樣也會打印出params = xxxxxx為數(shù)據(jù)的id值)。

我想這個例子應該能很好的解釋了Ember提示用戶需要的注意的問題。 只有直接用過瀏覽器訪問才會執(zhí)行包含了動態(tài)段的model回調(diào),否則不會執(zhí)行包含有動態(tài)段的回調(diào);如果沒有包含動態(tài)段的model回調(diào)不管是通過URL訪問還是通過link-to訪問都會執(zhí)行。你可以在路由postsmodel回調(diào)中添加一句打印日志的代碼,然后通過點擊首頁上的aboutposts切換路由,你可以看到控制臺打印出了你在model回調(diào)中添加的日志信息。

3,多模型

對于在一個model回調(diào)中同時返回多個模型的情況也是時常存在的。對于這種情況你需要在model回調(diào)中修改返回值為Ember.RSVP.hash對象類型。比如下面的代碼就是同時返回了兩個模型的數(shù)據(jù):一個是song,一個是album。

//  app/routes/favorites.js


import Ember from 'ember';


export default Ember.Route.extend({
    model: function() {
        return Ember.REVP.hash({
            songs: this.store.find('song'),
            albums: this.store.find('slbum')
        });
    }
});

然后在模板favorites.hbs中就可以使用{{#each}}把兩個數(shù)據(jù)集遍歷出來。遍歷的方式與普通的遍歷方式一樣。





<h2>Song list</h2>
<ul>
{{#each model.songs as |item|}}
    <li>{{item.name}}</li>
{{/each}}
</ul>
<hr>
<h2>Album list</h2>
<ul>
{{#each model.albums as |item|}}
    <li>{{item.name}}</li>
{{/each}}
</ul>

到此所有路由的model回調(diào)的情況介紹完畢,model回調(diào)其實就是把模型綁定到路由上。實現(xiàn)數(shù)據(jù)的初始化,然后把數(shù)據(jù)渲染到模板上顯示。這也是Ember推薦這么做的——就是把操作數(shù)據(jù)相關的處理放在route而不是放在controller。
博文完整代碼放在Github(博文經(jīng)過多次修改,博文上的代碼與github代碼可能又出入,不過影響不大!),如果你覺得博文對你有點用,請在github項目上給我點個star吧。您的肯定對我來說是最大的動力??!

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號