PA07▸🧩 Compose · 互動組合▸分頁
Pagination
分頁器
難度 ★★★★★標籤 分頁 · 省略 · 邊界3 min read
模式簡述
分頁看似簡單,邊界狀態超多:第一頁、最後一頁、只有一頁、零筆。 省略邏輯(1 … 4 5 6 … 20)才是分頁器的精華。
第 1 頁 / 共 10 頁
Claude Code Prompt
參考:PA07 pagination 技術:純 React,邊界邏輯 具體行為: - 顯示:< 1 ... 4 5 6 ... 20 >(current 高亮) - 第 1 頁:< disabled - 最後一頁:> disabled - < 7 頁:全部顯示,沒有省略 - 只有 1 頁:整個分頁器隱藏 - 0 筆:顯示「沒有資料」訊息,不顯示分頁 省略邏輯: - pages = [1] - 如果 current > 3,加 '…' - 加 [current-1, current, current+1] 範圍(夾在 2 到 total-1) - 如果 current < total-2,加 '…' - pages.push(total) 限制: - disabled 用 opacity-40 + cursor-not-allowed,不要 hidden - current 用 lab-accent 高亮,其他都 muted - 千萬不要顯示「1 2 3 ... 99 100」這種一字排開(手機會炸)
完整程式碼
function buildPages(current: number, total: number): (number | '…')[] {
if (total <= 7) return Array.from({ length: total }, (_, i) => i + 1)
const pages: (number | '…')[] = [1]
if (current > 3) pages.push('…')
for (let i = Math.max(2, current - 1); i <= Math.min(total - 1, current + 1); i++) {
pages.push(i)
}
if (current < total - 2) pages.push('…')
pages.push(total)
return pages
}
export function Pagination({ current, total, onChange }) {
if (total === 0) return <p>沒有資料</p>
if (total === 1) return null
const pages = buildPages(current, total)
return (
<nav>
<button disabled={current === 1} onClick={() => onChange(current - 1)}>‹</button>
{pages.map((p, i) =>
p === '…'
? <span key={i}>…</span>
: <button key={p} className={p === current ? 'active' : ''} onClick={() => onChange(p)}>{p}</button>
)}
<button disabled={current === total} onClick={() => onChange(current + 1)}>›</button>
</nav>
)
}何時用
- ✅ 文章列表、產品列表
- ✅ 後台資料表格(搭配 page size 選項)
- ✅ 搜尋結果頁
何時別用
- ❌ 動態瀑布流 / 社群動態(用 infinite scroll)
- ❌ 資料 < 一頁(隱藏分頁,不要顯示「1/1」)
- ❌ 需要快速跳到特定資料(用搜尋更直接)
我踩過的坑
-
沒處理只有一頁:顯示「1/1」+ 灰色 ‹ › 兩端,看起來像 bug。 只有一頁直接 return null。
-
省略邏輯沒夾邊界:current 1 的時候顯示「1 0 -1 ... 20」,超尷尬。 要用
Math.max(2, current - 1)跟Math.min(total - 1, current + 1)夾住。 -
disabled 用 hidden:第一頁時 ‹ 消失,按鈕位置會跳。 用 opacity-40 + cursor-not-allowed 保留空間。
相關模式
- 暫無