Ember.js 入門指南——查詢參數

查詢參數是在URL的問號(?)右邊部分,一般是鍵值對形式出現。 php

http://example.com/articles?sort=ASC&page=2

       好比這個URL的查詢參數有兩個,一個是sort,一個是page,它們的值分別是ASC2html

 

1,指定查詢參數      

       查詢參數一般是聲明爲controller類中。好比在當前活動路由articles下,你須要根據文章的類型category過濾,此時你必需要在controller內聲明過濾參數categoryjava

使用Ember CLI新建一個controllerroutejson

ember g controller article數組

ember g route articles;服務器

//  app/controllers/articles.js
 
import Ember from 'ember';
 
export default Ember.Controller.extend({
       queryParams: ['category'],
       category: null
});

    綁定一個查詢參數到URL,而且參數的值爲null。當你進入路由articles時,若是參數category的值發生變化會自動更新到controller中的category;反之亦然。你能夠設置一個默認值,好比把category設置爲「Java」。能夠在模板上獲取這個值。app

<!--    app/templates/articles.hbs    -->
{{outlet}}category = {{category}}

執行http://localhost:4200/articles,頁面會顯示出   category = Java。若是執行http://localhost:4200/articles?category=PHP,那麼頁面會顯示category = PHPide

       下面代碼演示了怎麼使用查詢參數:post

//  app/controllers/articles.js
 
import Ember from 'ember';
 
export default Ember.Controller.extend({
    queryParams: ['category'],
    category: null,
 
    //  定義一個返回數組的計算屬性,能夠直接在模板上遍歷
    filteredArticles: Ember.computed('category', 'model', function() {
           var category = this.get('category');
           var articles = this.get('model');
 
           if (category) {
               return articles.filterBy('category', category);
           } else {
               return articles;
           }
    })
});

       建立一個計算屬性,這個計算屬性是一個數組類型。因爲是計算屬性,而且這個計算屬性關聯了另外兩個屬性categorymodel,只要這兩個屬性其中之一發生改變都會致使filteredArticles發生改變,因此返回的數組元素也會跟着改變。學習

       route初始化測試數據。

//  app/routes/article.js
 
import Ember from 'ember';
 
export default Ember.Route.extend({
 
    model(params) {
          
           return [
                 { id: 1, title: 'Bower: dependencies and resolutions new', body: "In the bower.json file, I see 2 keys dependencies and resolutionsWhy is that so? I understand Bower has a flat dependency structure. So has it got anything to do with that ?", category: 'java' },
                 { id: 2, title: 'Highly Nested JSON Payload - hasMany error', body: "Welcome to the Ember.js discussion forum. We're running on the open source, Ember.js-powered Discourse forum software. They are also providing the hosting for us. Thanks guys! Please use this space for discussion abo… read more", category: 'php' },
                 { id: 3, title: 'Passing a jwt to my REST adapter new ', body: "This sets up a binding between the category query param in the URL, and the category property on controller:articles. In other words, once the articles route has been entered, any changes to the category query param in the URL will update the category property on controller:articles, and vice versa.", category: 'java' }
           ];
    }
});

 

下面看看怎麼在模板顯示數據,而且根據category顯示不一樣數據。

<!--  app/templates/articles.hbs  -->
 
<div class="col-md-4 col-xs-4">
 
<ul>
    <!-- 輸入的值會動態更新到controller  -->
       輸入分類:{{input value=category placeholder ='查詢的分類'}}
</ul>
 
<ul>
       <!-- 關鍵點:這裏使用的是filteredArticles而不是從route獲取的model -->
       {{#each filteredArticles as |item|}}
              <li>
                     {{#link-to 'articles.article' item}} {{item.title}}--{{item.category}} {{/link-to}}
              </li>     
       {{/each}}
</ul>
 
</div>
 
<div class="col-md-8 col-xs-8">
{{outlet}}
</div>

       精彩的時刻到了!!先執行http://localhost:4200/articles,此時顯示的是全部類型的數據。以下圖:

接着你就能夠作點好玩的事了,直接在輸入框輸入分類名。因爲計算屬性的特性會自動更新數組filteredArticles。因此咱們能夠看到隨着你輸入字符的變化顯示的數據也在變化!這個例子也說明了Ember計算屬性自動更新變化的強大!!用着確實爽啊!!

官網教程沒有說怎麼在模板中使用,講得也不是很明白,就給了一句「Now we just need to define a computed property of our category-filtered array that the articles template will render:」,也有多是我看不懂,反正摸索好一陣子才知道要這麼用!!

2使用link-to指定查詢參數    

       link-to助手使用query-params子表達式直接指定查詢參數,須要注意的是這個表達式須要放在括號內使用,切記別少了這個括號。

<!--  app/templates/articles.hbs  -->
……
<ul>
       {{#link-to 'articles' (query-params category='java')}} java {{/link-to}}
       <br>
       {{#link-to 'articles' (query-params category='php')}} php {{/link-to}}
       <br>
       {{#link-to 'articles' (query-params category='')}} all {{/link-to}}
</ul>
……

       在顯示數據的ul標籤後面新增上述兩個link-to助手。它們的做用分別是指定分類類型爲javaphp、所有。但用戶點擊三個鏈接直接顯示與鏈接指定類型匹配的數據(而且查詢的輸入框也變爲連接指定的類型值)。好比我點擊了第一個連接,輸入顯示以下圖:

3路由切換 

       route對象的transitionTo方法和controller對象的transitionToRoute方法均可以接受final類型的參數。而且這個參數是一個包括一個keyqueryParams的對象。

       修改前面已經建立好的路由posts.js

//  app/routes/posts.js
import Ember from 'ember';
export default Ember.Route.extend({
 
       beforeModel: function(params) {
 
              //  轉到路由articles上,而且傳遞查詢參數category,參數值爲Java
              this.transitionTo('articles', { queryParams: { category: 'java' }});
       }
});

       執行http://localhost:4200/posts後,能夠看到路由直接跳轉到http://localhost:4200/articles?category=java,實現了路由切換的同時也指定了查詢的參數。界面顯示的數據我就不截圖了,程序不出錯,顯示的都是categoryjava的數據。

       另外還有三種切換路由的方式。

//  能夠傳遞一個object過去
this.transitionTo('articles', object, { queryParams: { category: 'java' }});
 
// 這種方式不會改變路由,只是起到設置參數的做用,若是你在
//路由articles中使用這個方法,你的路由仍然是articles,只是查詢參數變了。
this.transitionTo({ queryParams: { direction: 'asc' }});
 
//  直接指定跳轉的URL和查詢參數
this.transitionTo('/posts/1?sort=date&showDetails=true');

       上面的三種方式請讀者本身編寫例子試試吧。光看不練假把式……

 

4選擇進入一個完整的路由    

       transitionTolink-to提供的參數僅會改變查詢參數的值,而不會改變路由的層次結構,這種路由的切換被認爲是不完整的,這也就意味着好比modelsetupController回調方法就不會被執行,只是使得controller裏的屬性值爲新的查詢參數值以及更新URL

       可是有些狀況是查詢參數改變須要從服務器從新加載數據,這種狀況就須要一個完整的路由切換了。爲了能在查詢參數改變的時候切換到一個完整的路由你須要在controller對應的路由中配置一個名爲queryParams哈希對象。而且須要設置一個名爲refreshModel的查詢參數,這個參數的值爲true

queryParams: {
       category: {
              refreshModel: true
       }
},
model: function(params) {
    return this.store.query('article', params);
}

      關於這段代碼演示實例請查看官方提供的代碼 


5,使用replaceState更新URL

       默認狀況下,Ember使用pushState更新URL來響應controller類中查詢參數屬性的變化,可是若是你想使用replaceState來替換pushState你能夠在route類中的queryParams哈希對象中設置replacetrue。設置爲true表示啓用這個設置。

queryParams: {
    category: {
        replaceState:true
    }
}

 

6,將控制器的屬性映射到不一樣的查詢參數鍵值

       默認狀況下,在controller類中指定的查詢屬性foo會綁定到名爲foo的查詢參數上。好比:?foo=123。你也能夠把查詢屬性映射到不一樣的查詢參數上,語法以下:

//  app/controllers/articles.js
import Ember from 'ember';
export default Ember.Controller.extend({
    queryParams: {
          category: 'articles_category'
    }
    category: null
});

       這段代碼就是把查詢屬性category映射到查詢參數articles_category上。

對於有多個查詢參數的狀況你須要使用數組指定。

//  app/controllers/articles.js
import Ember from 'ember';
export default Ember.Controller.extend({
       queryParams: ['page', 'filter', { category: 'articles_category' }],
    category: null,
    page: 1,
    filter: 'recent'
});

       上述代碼定義了三個查詢參數,若是須要把屬性映射到不一樣名的參數須要手動指定,好比category

7,默認值與反序列化

export default Ember.Controller.extend({
    queryParams: 'page',
    page: 1
});

       在這段代碼中設置了查詢參數page的默認值爲1

       這樣的設置會有兩種默認的行爲:

  1. 查詢的時候查詢屬性值會根據默認值的類型自動轉換,因此當用戶輸入http://localhost:4200/articles?page=1的時候page的值1會被識別成數字1而不是字符’1’,應爲設置的默認值1是數字類型。

  2. 當查詢的值正好是默認值的時候,該值不會被序列化到URL中。好比查詢值正好是?page=1這種狀況URL多是「/articles」,可是若是查詢值是「?page=2」URL確定是「/articles?page=2」

 

8,粘性的查詢參數值

       默認狀況下,在Ember中查詢參數是粘性的,也就是說若是你改變了查詢參數或者是離開頁面又回退回來,新的查詢值會默認在URL上,而不會自動清除(幾乎所見的URL都差很少是這種狀況)。這是個頗有用的默認設置,特別是當你點擊後退回到原頁面的時候顯示的數據沒有改變。    

       此外,粘性的查詢參數值會被加載的route存儲或者回復。好比,包括了動態段「/:post_id」的路由posts,以及路由對應的controller包含了查詢屬性「filter」。若是你導航到/badgers而且根據reookies過濾,而後再導航到/bears並根據best過濾,而後再導航到/potatose並根據lamest過濾。以下面的連接:

<ul>
       {{#link-to 'posts' 'badgers'}}Badgers{{/link-to}}<br>
       {{#link-to 'posts' 'bears'}}Bears{{/link-to}}<br>
       {{#link-to 'posts' 'potatoes'}}Potatoes{{/link-to}}<br>
</ul>

模板編譯以後獲得以下HTML代碼:

<ul>
    <a href="/badgers?filter=rookies">Badgers</a>
    <a href="/bears?filter=best">Bears</a>
    <a href="/potatoes?filter=lamest">Potatoes</a>
</ul>

       能夠看到一旦你改變了查詢參數,查詢參數就會被存儲或者是關聯到route所加載的model上。若是你想重置查詢參數你有以下兩種方式處理:

  1. link-to或者transitionTo上顯式指定查詢參數的值;

  2. 使用Route.resetController回調設置查詢參數的值並回退到切換以前的路由或者是改變model的路由。

下面的代碼片斷演示了一個查詢參數在controller中重置爲1,同時做用於切換前ActiclesRoutemodel。結果就是當返回到當前路由時查詢值已經被重置爲1

//  app/routes/article.js
 
import Ember from 'ember';
 
export default Ember.Route.extend({
 
       resetController(controller, isExiting, transition) {
              //  只有model發生變化的時候isExiting才爲false
              if (isExiting) {
                     //  重置查詢屬性的值
                     controller.set('page', 1);
              }
       }
});

 

某些狀況下,你不想是用查詢參數值限定路由模式,而是讓查詢參數值改變的時候路由也跟着改變而且會從新加載數據。這時候你可用在對應的controller類中設置queryParams哈希對象,在這對象中配置一個參數scopecontroller。以下:

queryParams: [{
    showMagnifyingGlass: {
              scope: 'controller'
       }
}]

       粘性的查詢參數值這個只是點理解起來好難的說,看下一遍下來都不知道這個有何用!!!如今仍是學習階段還沒真正在項目中使用這個特性,因此我也不知道怎麼解釋更容易理解,建議直接看官網教程吧!!

官方提供的示例:

·       查詢

·       排序: 端,不從新觸模型

·       排序: 器端,從新觸模型

·       和排序

·       爾值

·       用路由中的全局查詢參數

·       過設refreshModel:true實現完整過渡

·       過設replace:true實現replaceState

·       實現標籤w/ {{partial}}助手

·       路由名只有查詢參數的link-to

·       合成:序列化多行文本入框內容到URL(子表達式)

·      

·       使用冒號法映射不一樣的URL鍵值

 

以上的內容就是有關查詢參數的所有了,主要是理解了查詢參數的設置使用起來也就沒什麼問題。有點遺憾的是沒能寫出第4點的演示實例!能力有限只能遇到或者明白其使用的時候再補上了!!

相關文章
相關標籤/搜索