iT邦幫忙

2025 iThome 鐵人賽

DAY 7
0
Vue.js

Vue 新手學習紀錄系列 第 7

Day 7|分頁 Pagination

  • 分享至 

  • xImage
  •  

今日目標:

  • 表格下方加入頁數,每頁 10 筆資料
  • 若頁數 <= 1,則不顯示頁數切換

設計 Pagination.vue

在 src/components 中新增一個 Pagination.vue

<template>
  <div class="pagination-container">
    <div class="pagination-info">
      顯示第 {{ startItem }}-{{ endItem }} 項,共 {{ totalItems }} 項結果
    </div>
    
    <div class="pagination-controls">
      <button 
        class="pagination-btn prev-btn"
        :disabled="currentPage === 1"
        @click="$emit('page-change', currentPage - 1)"
      >
        ← 上一頁
      </button>
      
      <div class="page-numbers">
        <button
          v-for="page in visiblePages"
          :key="page"
          class="page-btn"
          :class="{ active: page === currentPage }"
          @click="$emit('page-change', page)"
        >
          {{ page }}
        </button>
      </div>
      
      <button 
        class="pagination-btn next-btn"
        :disabled="currentPage === totalPages"
        @click="$emit('page-change', currentPage + 1)"
      >
        下一頁 →
      </button>
    </div>
  </div>
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({
  currentPage: { type: Number, required: true },
  totalPages: { type: Number, required: true },
  totalItems: { type: Number, required: true },
  itemsPerPage: { type: Number, default: 10 }
})

const emit = defineEmits(['page-change'])

const startItem = computed(() => {
  return (props.currentPage - 1) * props.itemsPerPage + 1
})

const endItem = computed(() => {
  return Math.min(props.currentPage * props.itemsPerPage, props.totalItems)
})

const visiblePages = computed(() => {
  const pages = []
  const maxVisible = 5
  let start = Math.max(1, props.currentPage - Math.floor(maxVisible / 2))
  let end = Math.min(props.totalPages, start + maxVisible - 1)
  
  if (end - start + 1 < maxVisible) {
    start = Math.max(1, end - maxVisible + 1)
  }
  
  for (let i = start; i <= end; i++) {
    pages.push(i)
  }
  
  return pages
})
</script>

調整 App.vue 讓畫面能正確呈現頁數

<script setup>
import Pagination from './components/Pagination.vue'
...
const currentPage = ref(1)
const itemsPerPage = 10

function handlePageChange(page) {
  currentPage.value = page
  // Scroll to top when page changes
  window.scrollTo({ top: 0, behavior: 'smooth' })
}
const totalPages = computed(() => {
  return Math.ceil(filteredPosts.value.length / itemsPerPage)
})

const paginatedPosts = computed(() => {
  const start = (currentPage.value - 1) * itemsPerPage
  const end = start + itemsPerPage
  return filteredPosts.value.slice(start, end)
})
...
</script>

<template>
  <Header />
  <main>
    ...
    <div v-if="filteredPosts.length > 0">
      <div class="table-container">
        <PostTable :posts="paginatedPosts" @select="openDetail"/>
      </div>
      
      <Pagination 
        v-if="totalPages > 1"
        :current-page="currentPage"
        :total-pages="totalPages"
        :total-items="filteredPosts.length"
        :items-per-page="itemsPerPage"
        @page-change="handlePageChange"
      />
    </div>
    ...
  </main>
</template>

因為 code 比較長,就只貼了關於這個主題有更動的部分

今日成果

最後,附上昨天美化的網頁XDD
https://ithelp.ithome.com.tw/upload/images/20250921/20177929bZyQVUcS7w.pnghttps://ithelp.ithome.com.tw/upload/images/20250921/20177929j2FrvbN32T.png

底下是按下後會呈現的詳細資訊
https://ithelp.ithome.com.tw/upload/images/20250921/20177929AidS3Dijnx.png


上一篇
Day 6|呈現詳細資訊
下一篇
Day 8|實作新增資料
系列文
Vue 新手學習紀錄9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言