查詢參數(shù)是在URL的問(wèn)號(hào)(?)右邊部分,通常是鍵值對(duì)形式出現(xiàn)。
http://example.com/articles?sort=ASC&page=2
比如這個(gè)URL的查詢參數(shù)有兩個(gè),一個(gè)是sort
,一個(gè)是page
,它們的值分別是ASC
和2
。
查詢參數(shù)通常是聲明為controller
類中。比如在當(dāng)前活動(dòng)路由articles
下,你需要根據(jù)文章的類型category
過(guò)濾,此時(shí)你必須要在controller
內(nèi)聲明過(guò)濾參數(shù)category
。
使用Ember CLI新建一個(gè)controller
、route
:
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
});
綁定一個(gè)查詢參數(shù)到URL,并且參數(shù)的值為null
。當(dāng)你進(jìn)入路由articles
時(shí),如果參數(shù)category
的值發(fā)生變化會(huì)自動(dòng)更新到controller
中的category
;反之亦然。你可以設(shè)置一個(gè)默認(rèn)值,比如把category
設(shè)置為Java
??梢栽谀0迳汐@取這個(gè)值。
{{outlet}}
category = {{category}}
執(zhí)行http://localhost:4200/articles,頁(yè)面會(huì)顯示出 category = Java
。如果執(zhí)行http://localhost:4200/articles?category=PHP,那么頁(yè)面會(huì)顯示category = PHP
。
下面代碼演示了怎么使用查詢參數(shù):
// app/controllers/articles.js
import Ember from 'ember';
export default Ember.Controller.extend({
queryParams: ['category'],
category: null,
// 定義一個(gè)返回?cái)?shù)組的計(jì)算屬性,可以直接在模板上遍歷
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;
}
})
});
創(chuàng)建一個(gè)計(jì)算屬性,這個(gè)計(jì)算屬性是一個(gè)數(shù)組類型。由于是計(jì)算屬性,并且這個(gè)計(jì)算屬性關(guān)聯(lián)了另外兩個(gè)屬性category
和model
,只要這兩個(gè)屬性其中之一發(fā)生改變都會(huì)導(dǎo)致filteredArticles
發(fā)生改變,所以返回的數(shù)組元素也會(huì)跟著改變。
在route
初始化測(cè)試數(shù)據(jù)。
// 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' }
];
}
});
下面看看怎么在模板顯示數(shù)據(jù),并且根據(jù)category
顯示不同數(shù)據(jù)。
<div class="col-md-4 col-xs-4">
<ul>
輸入分類:{{input value=category placeholder ='查詢的分類'}}
</ul>
<ul>
{{#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>
精彩的時(shí)刻到了?。∠葓?zhí)行http://localhost:4200/articles,此時(shí)顯示的是所有類型的數(shù)據(jù)。如下圖:
接著你就可以做點(diǎn)好玩的事了,直接在輸入框輸入分類名。由于計(jì)算屬性的特性會(huì)自動(dòng)更新數(shù)組filteredArticles
。所以我們可以看到隨著你輸入字符的變化顯示的數(shù)據(jù)也在變化!這個(gè)例子也說(shuō)明了Ember計(jì)算屬性自動(dòng)更新變化的強(qiáng)大!!用著確實(shí)爽?。?!
官網(wǎng)教程沒(méi)有說(shuō)怎么在模板中使用,講得也不是很明白,就給了一句
Now we just need to define a computed property of our category-filtered array that the articles template will render:”
也有可能是我看不懂,反正摸索好一陣子才知道要這么用??!
link-to
助手使用query-params
子表達(dá)式直接指定查詢參數(shù),需要注意的是這個(gè)表達(dá)式需要放在括號(hào)內(nèi)使用,切記別少了這個(gè)括號(hào)。
……
<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>
……
在顯示數(shù)據(jù)的ul標(biāo)簽后面新增上述兩個(gè)link-to
助手。它們的作用分別是指定分類類型為java、php、全部。但用戶點(diǎn)擊三個(gè)連接直接顯示與連接指定類型匹配的數(shù)據(jù)(并且查詢的輸入框也變?yōu)殒溄又付ǖ念愋椭担1热缥尹c(diǎn)擊了第一個(gè)鏈接,輸入顯示如下圖:
route
對(duì)象的transitionTo
方法和controller
對(duì)象的transitionToRoute
方法都可以接受final
類型的參數(shù)。并且這個(gè)參數(shù)是一個(gè)包括一個(gè)key
為queryParams
的對(duì)象。
修改前面已經(jīng)創(chuàng)建好的路由posts.js
。
// app/routes/posts.js
import Ember from 'ember';
export default Ember.Route.extend({
beforeModel: function(params) {
// 轉(zhuǎn)到路由articles上,并且傳遞查詢參數(shù)category,參數(shù)值為Java
this.transitionTo('articles', { queryParams: { category: 'java' }});
}
});
執(zhí)行http://localhost:4200/posts后,可以看到路由直接跳轉(zhuǎn)到http://localhost:4200/articles?category=java,實(shí)現(xiàn)了路由切換的同時(shí)也指定了查詢的參數(shù)。界面顯示的數(shù)據(jù)我就不截圖了,程序不出錯(cuò),顯示的都是category
為java
的數(shù)據(jù)。
另外還有三種切換路由的方式。
// 可以傳遞一個(gè)object過(guò)去
this.transitionTo('articles', object, { queryParams: { category: 'java' }});
// 這種方式不會(huì)改變路由,只是起到設(shè)置參數(shù)的作用,如果你在
//路由articles中使用這個(gè)方法,你的路由仍然是articles,只是查詢參數(shù)變了。
this.transitionTo({ queryParams: { direction: 'asc' }});
// 直接指定跳轉(zhuǎn)的URL和查詢參數(shù)
this.transitionTo('/posts/1?sort=date&showDetails=true');
上面的三種方式請(qǐng)讀者自己編寫(xiě)例子試試吧。光看不練假把式……
transitionTo
和link-to
提供的參數(shù)僅會(huì)改變查詢參數(shù)的值,而不會(huì)改變路由的層次結(jié)構(gòu),這種路由的切換被認(rèn)為是不完整的,這也就意味著比如model
和setupController
回調(diào)方法就不會(huì)被執(zhí)行,只是使得controller
里的屬性值為新的查詢參數(shù)值以及更新URL。
但是有些情況是查詢參數(shù)改變需要從服務(wù)器重新加載數(shù)據(jù),這種情況就需要一個(gè)完整的路由切換了。為了能在查詢參數(shù)改變的時(shí)候切換到一個(gè)完整的路由你需要在controller
對(duì)應(yīng)的路由中配置一個(gè)名為queryParams
哈希對(duì)象。并且需要設(shè)置一個(gè)名為refreshModel
的查詢參數(shù),這個(gè)參數(shù)的值為true
。
queryParams: {
category: {
refreshModel: true
}
},
model: function(params) {
return this.store.query('article', params);
}
關(guān)于這段代碼演示實(shí)例請(qǐng)查看官方提供的代碼!
默認(rèn)情況下,Ember使用pushState
更新URL來(lái)響應(yīng)controller
類中查詢參數(shù)屬性的變化,但是如果你想使用replaceState
來(lái)替換pushState
你可以在route
類中的queryParams
哈希對(duì)象中設(shè)置replace
為true
。設(shè)置為true
表示啟用這個(gè)設(shè)置。
queryParams: {
category: {
replaceState:true
}
}
默認(rèn)情況下,在controller
類中指定的查詢屬性foo
會(huì)綁定到名為foo
的查詢參數(shù)上。比如:?foo=123
。你也可以把查詢屬性映射到不同的查詢參數(shù)上,語(yǔ)法如下:
// app/controllers/articles.js
import Ember from 'ember';
export default Ember.Controller.extend({
queryParams: {
category: 'articles_category'
}
category: null
});
這段代碼就是把查詢屬性category
映射到查詢參數(shù)articles_category
上。
對(duì)于有多個(gè)查詢參數(shù)的情況你需要使用數(shù)組指定。
// 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'
});
上述代碼定義了三個(gè)查詢參數(shù),如果需要把屬性映射到不同名的參數(shù)需要手動(dòng)指定,比如category
。
export default Ember.Controller.extend({
queryParams: 'page',
page: 1
});
在這段代碼中設(shè)置了查詢參數(shù)page
的默認(rèn)值為1
。
這樣的設(shè)置會(huì)有兩種默認(rèn)的行為:
1.查詢的時(shí)候查詢屬性值會(huì)根據(jù)默認(rèn)值的類型自動(dòng)轉(zhuǎn)換,所以當(dāng)用戶輸入http://localhost:4200/articles?page=1的時(shí)候page
的值1
會(huì)被識(shí)別成數(shù)字1
而不是字符'1'
,應(yīng)為設(shè)置的默認(rèn)值1
是數(shù)字類型。
2.當(dāng)查詢的值正好是默認(rèn)值的時(shí)候,該值不會(huì)被序列化到URL中。比如查詢值正好是?page=1
這種情況URL可能是/articles
,但是如果查詢值是?page=2
,URL肯定是/articles?page=2
。
默認(rèn)情況下,在Ember中查詢參數(shù)是“粘性的”,也就是說(shuō)如果你改變了查詢參數(shù)或者是離開(kāi)頁(yè)面又回退回來(lái),新的查詢值會(huì)默認(rèn)在URL上,而不會(huì)自動(dòng)清除(幾乎所見(jiàn)的URL都差不多是這種情況)。這是個(gè)很有用的默認(rèn)設(shè)置,特別是當(dāng)你點(diǎn)擊后退回到原頁(yè)面的時(shí)候顯示的數(shù)據(jù)沒(méi)有改變。
此外,粘性的查詢參數(shù)值會(huì)被加載的route
存儲(chǔ)或者回復(fù)。比如,包括了動(dòng)態(tài)段/:post_id
的路由posts
,以及路由對(duì)應(yīng)的controller
包含了查詢屬性filter
。如果你導(dǎo)航到/badgers
并且根據(jù)reookies
過(guò)濾,然后再導(dǎo)航到/bears
并根據(jù)best
過(guò)濾,然后再導(dǎo)航到/potatose
并根據(jù)lamest
過(guò)濾。如下面的鏈接:
<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>
可以看到一旦你改變了查詢參數(shù),查詢參數(shù)就會(huì)被存儲(chǔ)或者是關(guān)聯(lián)到route
所加載的model
上。如果你想重置查詢參數(shù)你有如下兩種方式處理:
1.在link-to
或者transitionTo
上顯式指定查詢參數(shù)的值;
2.使用Route.resetController
回調(diào)設(shè)置查詢參數(shù)的值并回退到切換之前的路由或者是改變model
的路由。
下面的代碼片段演示了一個(gè)查詢參數(shù)在controller
中重置為1
,同時(shí)作用于切換前ActiclesRoute
的model
。結(jié)果就是當(dāng)返回到當(dāng)前路由時(shí)查詢值已經(jīng)被重置為1
。
// app/routes/article.js
import Ember from 'ember';
export default Ember.Route.extend({
resetController(controller, isExiting, transition) {
// 只有model發(fā)生變化的時(shí)候isExiting才為false
if (isExiting) {
// 重置查詢屬性的值
controller.set('page', 1);
}
}
});
某些情況下,你不想是用查詢參數(shù)值限定路由模式,而是讓查詢參數(shù)值改變的時(shí)候路由也跟著改變并且會(huì)重新加載數(shù)據(jù)。這時(shí)候你可用在對(duì)應(yīng)的controller
類中設(shè)置queryParams
哈希對(duì)象,在這對(duì)象中配置一個(gè)參數(shù)scope
為controller
。如下:
queryParams: [{
showMagnifyingGlass: {
scope: 'controller'
}
}]
粘性的查詢參數(shù)值這個(gè)只是點(diǎn)理解起來(lái)好難的說(shuō),看下一遍下來(lái)都不知道這個(gè)有何用?。。‖F(xiàn)在還是學(xué)習(xí)階段還沒(méi)真正在項(xiàng)目中使用這個(gè)特性,所以我也不知道怎么解釋更容易理解,建議直接看官網(wǎng)教程吧?。?/p>
說(shuō)明:本文是基于官方2.0參考文檔縮寫(xiě),相對(duì)于其他版本內(nèi)容會(huì)有出入。
以上的內(nèi)容就是有關(guān)查詢參數(shù)的全部了,主要是理解了查詢參數(shù)的設(shè)置使用起來(lái)也就沒(méi)什么問(wèn)題。有點(diǎn)遺憾的是沒(méi)能寫(xiě)出第4點(diǎn)的演示實(shí)例!能力有限只能遇到或者明白其使用的時(shí)候再補(bǔ)上了?。?/p>
博文完整代碼放在Github(博文經(jīng)過(guò)多次修改,博文上的代碼與github代碼可能又出入,不過(guò)影響不大?。?,如果你覺(jué)得博文對(duì)你有點(diǎn)用,請(qǐng)?jiān)趃ithub項(xiàng)目上給我點(diǎn)個(gè)star
吧。您的肯定對(duì)我來(lái)說(shuō)是最大的動(dòng)力!!
更多建議: