前言
接下來講講製作分頁邏輯的部分,好在本身 API 就已經有判斷分頁了
邏輯思考
一般來講我們要製作分頁的時候動作是滿多是在的分頁的邏輯上面,首先會有這幾個重點
- 總共有幾頁 - total_pages
- 當前在第幾頁 - current_pages
- 每一頁呈現多少資料 - per_page
- 頁面頁數
以這個範例 API 來講可以有兩種做法,一種是所有資料的 api,另一種則是使用後端幫我們處理好的 api,但是在製作之前我們會先建立一個 Pagination_1.vue 與 Pagination_2.vue 的檔案,這兩支分別會有兩種做法
- Pagination_1.vue - 比較原生較重邏輯的方式製作,所以會使用取得全部資料來製作
- Pagination_2.vue - 使用後端處理好的現成分頁邏輯製作
所以這章節將會拆成兩部分,一部分是講解自己處理資料,另一部分是由後端處理好的方式
模板
這邊會直接使用 bootstrap 所提供的 Pagination 模板做開發 (已轉 pug)
1 2 3 4 5 6 7 8 9 10 11 12
| nav(aria-label='Page navigation example') ul.pagination li.page-item a.page-link(href='#') Previous li.page-item a.page-link(href='#') 1 li.page-item a.page-link(href='#') 2 li.page-item a.page-link(href='#') 3 li.page-item a.page-link(href='#') Next
|

這邊我們將會使用取得所有資料的 API 來製作

AJAX 的方法我就直接提供在下方,主要是修改再 Products.vue,所以原本的 getProduct
就會有點不太一樣

將會調整成改取得所有資料的 API,那這與原本的 API 是有差異的,原本的 API 拉回來的資料是像這樣子

但取得所有資料的 API 就變成了物件型態,是不太一樣的

首先要將原本儲存資料的 products 改成陣列

然後將拉回資料的部分改成 push
的方式

1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const vm = this; const url = `${process.env.VUE_APP_HEXURL}/api/${process.env.VUE_APP_HEXNAME}/admin/products/all`; vm.isLoading = true; vm.$http.get(url) .then((response) => { if (response.data.success) { vm.products.push(response.data.products); } vm.isLoading = false; }) .catch((error) => { vm.$bus.$emit('message:push', error, 'danger'); vm.isLoading = false; });
|
但是你會發現不能正常顯示資料,原因是出在第一層跑出迴圈是拉出所有陣列的第一層導致,所以正確程式碼部分要多做迴圈處理,但是這邊要注意資料是 object 型態,所以要使用 for...in...
來處理物件資料
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const vm = this; const url = `${process.env.VUE_APP_HEXURL}/api/${process.env.VUE_APP_HEXNAME}/admin/products/all`; vm.isLoading = true; vm.$http.get(url) .then((response) => { if (response.data.success) { let objectProducts = response.data.products; for(let item in objectProducts) { vm.products.push(objectProducts[item]); } } vm.isLoading = false; }) .catch((error) => { vm.$bus.$emit('message:push', error, 'danger'); vm.isLoading = false; });
|
那麼這邊就將資料處理方面給完成了
分頁邏輯
這邊分頁的邏輯是比較長的,也比較複雜唷
首先我們要先取得設置相關的資料欄位(該這樣講嗎?),所以 data
中會新增 pagination
的物件資料

在前面有講到我們會需要這幾個資料
- 總共有幾頁 - total_pages
- 當前在第幾頁 - current_pages
- 每一頁呈現多少資料 - per_page
- 頁面頁數
但是這邊還少一個 全部資料數量,所以程式碼就可以這樣寫
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| const vm = this; const url = `${process.env.VUE_APP_HEXURL}/api/${process.env.VUE_APP_HEXNAME}/admin/products/all`; vm.isLoading = true; vm.$http.get(url) .then((response) => { if (response.data.success) { let objectProducts = response.data.products; for(let item in objectProducts) { vm.products.push(objectProducts[item]); } vm.pagination.totalResult = vm.products.length; vm.pagination.per_page = 10; vm.pagination.pageTotal = Math.ceil(vm.pagination.totalResult / vm.pagination.per_page); vm.pagination.currentPage = 1; if (vm.pagination.currentPage > vm.pagination.pageTotal) { vm.pagination.currentPage = vm.pagination.pageTotal; } const minPage = (vm.pagination.currentPage * vm.pagination.per_page) - vm.pagination.per_page + 1; const maxPage = (vm.pagination.currentPage * vm.pagination.per_page); console.log(`總資料數量:${vm.pagination.totalResult},每頁數量:${vm.pagination.per_page},總頁數:${vm.pagination.pageTotal},當前頁數:${vm.pagination.currentPage},每頁第一筆:${minPage},每頁最後一筆${maxPage}`) } vm.isLoading = false; }) .catch((error) => { vm.$bus.$emit('message:push', error, 'danger'); vm.isLoading = false; });
|
那麼結果就會像這樣

接下來就準備來做資料處理哩
1 2 3 4 5 6 7 8 9 10 11 12
|
vm.products = []; vm.cacheProducts.forEach((item, index) => { let num = index + 1; if (num >= minPage && num <= maxPage) { vm.products.push(item); } });
|
這樣子就成功地將資料做了分頁篩選

但是這邊還有幾個地方還沒有做調整,首先我們必須透過 components 來切換分頁,所以會有一個 Pagination_1.vue 接收我們的當前分頁,另外 getProduct()
也必須額外傳入參數,也就是當前分頁參數,所以這邊的完整程式碼就會變成這樣 (請小心服用很長)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| getProduct(currentPage = 1) { const vm = this; const url = `${process.env.VUE_APP_HEXURL}/api/${process.env.VUE_APP_HEXNAME}/admin/products/all`; vm.isLoading = true; vm.$http.get(url) .then((response) => { if (response.data.success) { const objectProducts = response.data.products; vm.cacheProducts = []; for (const item in objectProducts) { vm.cacheProducts.push(objectProducts[item]); } vm.pagination.totalResult = vm.cacheProducts.length; vm.pagination.per_page = 10; vm.pagination.pageTotal = Math.ceil(vm.pagination.totalResult / vm.pagination.per_page); vm.pagination.currentPage = currentPage; if (vm.pagination.currentPage > vm.pagination.pageTotal) { vm.pagination.currentPage = vm.pagination.pageTotal; } const minPage = (vm.pagination.currentPage * vm.pagination.per_page) - vm.pagination.per_page + 1; const maxPage = (vm.pagination.currentPage * vm.pagination.per_page); vm.products = []; vm.cacheProducts.forEach((item, index) => { const num = index + 1; if (num >= minPage && num <= maxPage) { vm.products.push(item); } }); } vm.isLoading = false; }) .catch((error) => { vm.$bus.$emit('message:push', error, 'danger'); vm.isLoading = false; }); },
|
分頁元件
接下來準備製作分頁元件,這邊會使用到的觀念式 props、emit,這邊直接提供模板 template
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <template lang="pug"> div nav(aria-label='Page navigation example') ul.pagination.justify-content-center li.page-item(v-for='pages in paginationService.pageTotal', :key='pages', :class="{'active': paginationService.currentPage === pages}") a.page-link(href='#', @click.prevent='getPagesService(pages)') {{ pages }} </template>
<script> export default { props: { paginationService: { type: Object, }, }, methods: { getPagesService(item) { this.$emit('pageService', item); }, }, }; </script>
|
然後回到 products.vue,將 Pagination_1.vue 引入
1
| import pagination1Components from '../shared/Pagination_1.vue';
|
(請記得插入模板內)
那模板那邊插入就是這樣
1
| pagination1Components(:paginationService='pagination')
|

接下來就是切頁做調整,當我們點擊第二頁時,Pagination_1
要將資料往外傳給 getProduct
來做切頁動作,所以就會這樣寫
1
| pagination1Components(:paginationService='pagination', v-on:pageService="getProduct")
|
那麼這樣子就成功做出分頁功能哩~

並且也可以切換頁面

補充
如果對於 props 與 emit 不熟悉的話,可以看看我所撰寫的這一篇文章
props 與 emit 的傳遞方式