Ember.js 入門指南——指定與路由關聯的模型

路由其中一個很重要的職責就是加載適合的model,初始化數據,而後在模板上顯示數據。javascript

1,普通model關聯

//  app/router.js
 
//  ……
 
Router.map(function() {
    this.route('posts');
});
 
export default Router;

   對於posts這個路由若是要加載名爲postmodel要怎麼作呢?代碼實現很簡單,其實在前面的代碼也已經寫過了。你只須要重寫model回調,在回調中返回獲取到的model便可。html

//  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回調能夠返回一個Ember Data記錄,或者返回任何的promise對象(Ember Data也是promise對象),又或者是返回一個簡單的javascript對象、數組均可以。可是須要等待數據加載完成纔會渲染模板,因此若是你是使用Ember.$.getJSON('https://api.github.com/repos/emberjs/ember.js/pulls');獲取遠程數據頁面上會有一段時間是空白的,其實就是在加載數據,不過這樣的用戶體驗並很差,不過你也不須要擔憂這個問題,Ember已經提供瞭解決辦法。還記得上一篇的截圖的路由表嗎?是否是每一個路由都有一個xxx_loading路由,這個路由就是在數據加載的時候執行的,有關xxx_loading更多詳細的信息在後面的博文介紹。java

 

2,動態model

       一個route有時候只加載同一個model,好比路由「/photos」就一般是加載模型photo。若是用戶離開或者是從新進入這個路由模型也不會改變。git

       然而,有些狀況下路由所加載的model是變化的。好比在一個圖片展現的APP中,路由「/photos」會加載一個photo模型集合並渲染到模板photos上。當用戶點擊其中一幅圖片的時候路由只加載被點擊的model數據,當用戶點擊另一張圖片的時候加載的又是另一個model而且渲染到模板上,並且這兩次加載的model數據是不同的。github

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

       Ember應用中能夠經過定義動態段實現加載不一樣的模型。有關動態段的知識在前面的《Ember.js 指南——{{link-to}} 助手》和《Ember.js 指南——路由定義》已經作過介紹。數組

       一旦在路由中定義了動態段Ember就會從URL中提取動態段的值做爲model回調的第一個參數。promise

//  app/router.js
// ……
 
Router.map(function() {
    this.route('posts', function() {
        this.route('post', { path: '/:post_id'});
    });
});
 
export default Router;

    這段代碼定義了一個動態段「:post_id」,記得動態段是以「:」開頭。而後在model回調中使用動態段獲取數據。瀏覽器

//  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回調中也是使用在路由中定義的動態段,並把這個動態段做爲參數傳遞給Ember的方法findRecordEmber會把URL對應位置上的數據解析到這個動態段上。緩存

       注意:model中的動態段只在經過URL訪問的時候纔會被解析。若是你是經過其餘方式(好比使用link-to進入路由)轉入路由的,那麼路由中model回調方法裏的動態不會被解析,所請求的數據會直接從上下文中獲取(你能夠把上下文想象成ember的緩存)。下面的代碼將爲你演示這個說法:

1,首先建立一個modelember 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)在建立路由post,同時也會自動建立出子模板post.hbs。建立完成以後會獲得以下兩個文件:

  1. app/routes/posts/post.js

  2. app/templates/posts/post.hbs

3,修改路由posts.js,在model回調中返回設定的數據。
//  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"
                  }
              ];
       }
});
  4,修改posts.hbs,遍歷顯示全部的數據。
<ul>
       {{#each model as |item|}}
              <li>
                     {{#link-to 'posts.post' item}}{{item.title}}{{/link-to}}
              </li>     
       {{/each}}
</ul>
 
<hr>
{{outlet}}
 5,修改子路由post.js,使得子路由根據動態段返回匹配的數據。
// 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

<!-- app/templates/posts/post.hbs -->
 
<h2>{{model.title}}</h2>
<p>{{model.body}}</p>

到此,所有所需的測試數據和代碼已經編寫完畢。下面執行http://localhost:4200/posts,能夠看到界面上顯示了全部在路由postsmodel回調中設置的測試數據。查看頁面的HTML代碼:

能夠看到每一個鏈接的動態段都被解析成了數據的id屬性值。

    注意:隨便點擊任意一個,注意看瀏覽器控制檯打印的信息。

    我點擊了以第一個鏈接,瀏覽器的URL變爲

看瀏覽器的控制檯是否是並無打印出params = -JzySrmbivaSSFG6WwOk,在點擊其餘的鏈接結果也是同樣的,瀏覽器控制檯沒有打印出任何信息。

       下面我咱們直接在瀏覽器地址欄上輸入:http://localhost:4200/posts/-JzyUqbJcT0ct14OizMo而後按enter執行,注意看瀏覽器控制檯打印的信息!!!此時打印了「params = -JzyUqbJcT0ct14OizMo」,你能夠用一樣的方式執行另外兩個連接的地址。一樣也會打印出「params = xxx」xxx爲數據的id值)。

   我想這個例子應該能很好的解釋了Ember提示用戶須要的注意的問題:

  •     只有直接用過瀏覽器訪問纔會執行包含了動態段的model回調,不然不會執行包含有動態段的回調;

  •     若是沒有包含動態段的model回調不論是經過URL訪問仍是經過link-to訪問都會執行。

你能夠在路由postsmodel回調中添加一句打印日誌的代碼,而後經過點擊首頁上的aboutposts切換路由,你能夠看到控制檯打印出了你在model回調中添加的日誌信息。

3多模型

       對於在一個model回調中同時返回多個模型的狀況也是時常存在的。對於這種狀況你須要在model回調中修改返回值爲Ember.RSVP.hash對象類型。好比下面的代碼就是同時返回了兩個模型的數據:一個是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}}把兩個數據集遍歷出來。遍歷的方式與普通的遍歷方式同樣。

<!--  app/templates/favorites.hbs -->
 
<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回調的狀況介紹完畢,model回調其實就是把模型綁定到路由上。實現數據的初始化,而後把數據渲染到模板上顯示。   這也是Ember推薦這麼作的就是把操做數據相關的處理放在route而不是放在controller

相關文章
相關標籤/搜索