CHAPTER 22 · 180 MINUTES
產品列表、資料渲染與分頁
資料很多時,不把整座書架倒出來;依頁碼切出一小段,再讓卡片、頁碼與按鈕同步。
LEARNING GOALS
本章結束時,你能做出什麼
01先搜尋與價格篩選
從完整 products 依關鍵字與價格產生 filteredProducts,條件改變時回到第 1 頁。
02再分頁並集中 render
只對篩選結果切頁,由同一個 render 同步卡片、頁碼與結果數。
03守住空結果與首末頁
0 筆顯示 0 / 0 且雙鍵停用;首末頁不能翻到不存在的頁碼。
進場檢核與作品接力
可觀察目標:兩種查找操作可單獨或組合使用,條件變更後回第一頁;查找結果每頁最多三筆,卡片與頁碼同步;首末頁按鈕正確停用,空資料不會顯示第 1 / 0 頁。
- 具備第 21 章成果:能說出 id/name/price rows 契約與 MOCK/LIVE/FALLBACK 邊界:不看答案,展示或口述第 21 章成果,並說出一項可見證據。 需要補強時從這裡接回
- 能從 Starter、Checkpoint 與 Solution 中辨識目前工作階段:開啟本章主講義,指出 TASK-01 的修改檔案、可見結果與第一個 Checkpoint。 需要補強時從這裡接回
- 能用「操作後看見什麼」描述驗收證據:閱讀三個任務後,選一題說出操作條件與預期可見結果。 需要補強時從這裡接回
輸入:第 21 章已驗收的 id/name/price rows 契約與 MOCK/LIVE/FALLBACK 邊界;本章用七筆本地 fixture 重現同一契約
本章輸出:完成可前後翻頁的產品列表
產物類型:mainline;後續用途:第 28 章
PROBLEM & ANALOGY
不是刪資料,而是一次拿一層書架
第 21 章已驗收 id/name/price rows 契約;本章用七筆本地 fixture 重現同一入口。完整陣列仍保留,只依 page 算起點與終點,再用 slice 取得本頁。
本章要解決:頁碼、卡片與按鈕若各自更新,容易不同步或翻到空白頁。
合回共同作品:產品案例會成為作品集中的可操作資料頁。
必會能自己完成
page、pageSize、slice、totalPages、render 與 disabled。
辨識看得懂即可
offset 是從第幾筆開始;能代入數字,不要求背英文。
不教刻意延後
伺服器分頁、無限滾動、虛擬清單與 URL query 同步。
CORE IDEAS
原始資料 → 搜尋/價格篩選 → 分頁 → render
- 原始資料:
products 保留完整資料,不因搜尋或翻頁被覆寫。 - 搜尋/價格篩選:
getFilteredProducts() 同時套用關鍵字與價格,條件改變就把 page 重設為 1。 - 分頁:以篩選後資料計算
totalPages,再用 slice(start, end) 取得目前頁資料。 - render:唯一出口同時更新安全文字卡片、結果數、頁碼與按鈕
disabled 狀態。
Checkpoint 前必做流程追蹤:先篩選,再分頁。固定一組原始資料,先輸入關鍵字與價格,記錄 filteredProducts 數量;再代入 start/end 取得 pageItems;最後確認 render 顯示相同筆數。空結果必須走到 0 / 0 與雙鍵停用。
課堂刻意錯誤:允許 page 超過 totalPages,或只加灰色 class、沒有真的設定 disabled。
- 印出 page、pageSize、start、end 與 totalPages。
- 用第一頁與最後一頁實際代入,確認 slice 不包含 end。
- 空白頁先查 page 是否越界,再查資料。
- 確認 disabled 屬性與事件條件一致,不只改外觀。
- 重跑「第一頁上一頁、最後頁下一頁」兩個邊界。
症狀 01
切換後出現空白頁
先查:印出 page、start、end、totalPages,查頁碼是否越界。
症狀 02
頁碼和卡片對不上
先查:確認事件只改 page,再由同一個 render 更新畫面。
症狀 03
按鈕看似停用仍能點
先查:檢查 disabled 屬性與事件條件。
PRACTICE CONTRACT
Starter 到 Solution 使用同一批產品
開始前先確認這四件事
- 我先測試關鍵字、價格與無結果。
- 我能用數字代入 start、end 與 totalPages。
- 原始陣列不會因 slice 被切掉。
- 我會測試第一頁上一頁與最後頁下一頁。
TASK-01
依關鍵字與價格查找產品
檔案:script.js
位置:getFilteredProducts()
結果:可以關鍵字、價格或兩者查找產品
TASK-02
分頁並渲染查找結果
檔案:script.js
位置:getPageItems()、render()
結果:查找結果每頁最多三筆,卡片與頁碼同步
TASK-03
限制上一頁與下一頁邊界
檔案:script.js
位置:updateControls()
結果:首末頁按鈕正確停用,無查找結果時顯示 0 / 0 且兩鍵停用
-
01
先讀任務
Starter
完整資料與函式骨架。
累積完成 0/3 個任務
開始練習 →
-
02
完成第一項
Checkpoint 1
完成 TASK-01。
累積完成 1/3 個任務
繼續第一步 →
-
03
累積第二項
Checkpoint 2
再完成 TASK-02。
累積完成 2/3 個任務
繼續第二步 →
-
04
核對完成品
Solution
只補 TASK-03,操作首末頁。
累積完成 3/3 個任務
查看完整結果 →
✓網頁版答案位置對照卡住時先完成 Checkpoint 2,再查看每個 TASK 對應的檔案與位置。→
30 秒說法可以直接照這個句型練習:
目前第 ______ 頁,每頁 ______ 筆,start 是 ______、end 是 ______;totalPages 是 ______。
證據要包含無結果狀態;0 / 0 與兩個停用按鈕也是產品體驗的一部分。
錄下從第一頁翻到最後一頁的操作,畫面須同時看見產品、頁碼與停用按鈕;再口頭代入第二頁的 start、end。
交件前自我檢核
4 項 · 點選每一列完成自評
下一章:從讀取產品轉向驗證使用者輸入並安全 POST。
下一步:前往第 23 章「表單驗證、POST 與資料寫入」,帶著本章輸出繼續累積作品。