Node.js 實作分頁
一樣延續 使用 Node.js 與 RESTful API 架構來串接 mongoDB 並部署到 Heroku,跟 Node.js 實作登入及驗證 來延伸實作分頁功能。
製作分頁功能,首先要考慮四個要素:
- 總頁數 = 總資料量/每頁每頁資料量
- 目前頁數 = 預設第一頁(之後依照 query 參數傳入)
- 每頁資料量 = 自行設定
- 當前頁面資料 = 按照目前頁數及每頁資料量找出範圍區間後顯示
後端
有了四個要素,就可以做出功能了。
- 連接資料庫後,取得資料
- 根據上面的四要素,算出參數
- 篩選出要顯示的資料
- 回傳資料及參數給 client 端
邏輯控制
在邏輯控制加入分頁方法
./controllers/restaurants.js
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
| getRestaurantsPage: (req, res) => { // 接收前端所查詢的頁面資料 ?page=1 // 由於接收到的資料是字串,用 parseInt() 轉換成數字 let currentPage = parseInt(req.query.page) || 1 db.collection('restaurants').find().toArray((err, result) => { if (err) return console.log(err) const totalResult = result.length // 每頁資料量 const perpage = 3 // 總頁數 const pageTotal = Math.ceil(totalResult / perpage) // 預設當前頁數, // let currentPage = 1 // 當前頁不能超過總頁數 if (currentPage > pageTotal) { currentPage = pageTotal } // 第幾筆資料索引範圍 const minItem = (currentPage * perpage) - perpage + 1 const maxItem = (currentPage * perpage)
// console.log(totalResult, pageTotal, currentPage, minItem, maxItem) const temp = [] result.forEach((item, i) => { let itemNum = i + 1 if (itemNum >= minItem && itemNum <= maxItem) { // console.log(item.name, i) temp.push(item) } }) // console.log(temp) res.status(200).send({ data: temp, pagination: { total_pages: pageTotal, current_page: currentPage, has_pre: currentPage > 1, has_next: currentPage < pageTotal, category: null } }) }) },
|
路由設定
./routes/restaurants.js
router.get('/page', getRestaurantsPage)
API: http://localhost:3000/restaurants/page?page=1
前端
Vue 前端製作部分:
html(使用樣板)
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
| <nav aria-label="Page navigation example"> <ul class="pagination"> <li class="page-item" :class="{'disable': !pagination.has_pre}"> <a class="page-link" href="#" aria-label="Previous" @click.prevent="getLocation(pagination.current_page - 1)" > <span aria-hidden="true">«</span> <span class="sr-only">Previous</span> </a> </li> <li class="page-item" v-for="page in pagination.total_pages" :key="page" :class="{'active': pagination.current_page === page}" > <a class="page-link" href="#" @click.prevent="getLocation(page)">{{ page }}</a> </li> <li class="page-item"> <a class="page-link" href="#" aria-label="Next" @click.prevent="getLocation(pagination.current_page + 1)" > <span aria-hidden="true">»</span> <span class="sr-only">Next</span> </a> </li> </ul> </nav>
|
加上 pagination 資料欄位
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| export default { data: () => ({ ... pagination: {}, ... }), methods: { getLocation(page = 1) { // 用 axios 非同步取得資料 const api = `${process.env.VUE_APP_APIPATH}/restaurants/page?page=${page}` this.$http.get(api).then(Response => { this.data = Response.data.data this.pagination = Response.data.pagination }) }, },
|
參考:
六角學院 Node.js 課程
https://wiki.jikexueyuan.com/project/express-mongodb-setup-blog/