[VueJS] 在 v-for 列表中透過 filter 完成搜尋與分頁的功能
最近 Vue.js 正夯,所以手上幾個東西打算用這個來改寫,關於 Vue.js 的基本介紹可以參考小弟的投影片,這裡就不再贅述。
有用過 Vue.js 開發的朋友一定知道它提供的 filter 功能十分強大,在 v-for
列表中使用 filterBy
可以在一行內完成列表搜尋的功能:
<div id="filter-by-example">
<input v-model="n">
<ul>
<!-- 透過 input 欄位的 v-model n 與 user.name 做模糊比對 -->
<li v-for="user in users | filterBy n in 'name'">
{{ user.name }}
</li>
</ul>
</div>
若是要限制顯示的筆數也能用 limitBy
做到,進而完成分頁的功能。
<!-- 只顯示前 10 個元素 -->
<div v-for="item in items | limitBy 10"></div>
<!-- 顯示第 5 到 15 筆元素-->
<div v-for="item in items | limitBy 10 5"></div>
這次遇到的問題是這樣的,如果我們想要同時完成「搜尋」與「分頁」的需求,光靠 filterBy
與 limitBy
就不是那麼容易做到,還好 Vue.js 提供了自訂 filter 的功能:先用 filterBy 過濾,再透過自訂 recordLength 記錄過濾後的資料數量,最後再用 limitBy 搭配頁籤切換頁面。
小心 filter 的順序,filter 會依序執行,然後再繼續下個 filter。
<tr v-for=" r in rows
| filterBy filter_name in 'name'
| recordLength 'filteredRowCount'
| limitBy countOfPage pageStart ">
<td>......</td>
</tr>
然後是自定的 filter recordLength
:
result 代表傳入的資料, key 則是從 view 帶入的參數,這個範例是 filteredRowCount
。
這裡透過 vm.$set
來將過濾後的數量指定至 vue 實體,以便可以直接在 Vue 實體使用。
Vue.filter('recordLength', function (result, key) {
this.$set(key, result.length);
return result;
});
最後在頁籤的部分,我們就可以簡單透過 filter_name
欄位是否空白來切換是否透過 filteredRowCount
計算總頁數:
totalPage: function(){
if( this.filter_name.trim() === '' ) {
return Math.ceil(this.rows.length / this.countOfPage);
}
else{
return Math.ceil(this.filteredRowCount / this.countOfPage);
}
}
完整的 demo 如下: