題幹與適用場景
這道前端題考察長清單的互動狀態、網路邊界和可存取性。重點不是把觀察器接到哨兵元素,而是讓載入、取消、失敗、重試、位置恢復和替代導覽形成完整契約。
面試官考察什麼
- 能否用 Intersection Observer 或等價機制觸發載入,並控制預取距離。
- 能否透過游標、請求去重和順序保護避免重複頁、亂序頁和無限重試。
- 能否讓鍵盤、螢幕閱讀器、縮放和低速網路使用者獲得可見且可操作的狀態。
- 能否在無限捲動不適合時提供分頁、跳到主要內容和位置恢復。
回答前需要澄清的問題
先確認清單是時間線、搜尋結果還是網格,排序是否穩定,服務端能否提供游標,單頁大小和目標首屏延遲是多少。也要確認是否要求分享某個位置、是否支援返回後恢復捲動、內容高度是否變動,以及是否存在行動裝置流量限制。
30 秒回答框架
我會使用穩定游標分頁和可移除的載入哨兵。只有沒有進行中的請求、還有下一頁且哨兵進入預取區時才載入;回應按游標去重並保持順序。載入、失敗、重試和已到末端都顯示為可聚焦狀態。清單提供明確的分頁或「載入更多」替代入口、跳到主要內容和返回位置恢復,避免把捲動當成唯一導覽。
分步驟深入解答
1. 定義資料與位置契約
優先使用不受插入資料影響的游標,回應攜帶下一游標和穩定的項目 id。客戶端維護已知游標集合、項目 id 集合和目前請求狀態,避免用頁碼在前方插入時造成重複或遺漏。返回頁面時記錄路由、游標和捲動偏移,並在資料重新可用後恢復到可見項目。
2. 設計觸發與並行控制
Intersection Observer 只負責發出「接近底部」的訊號,不直接啟動無界請求。觸發前檢查 hasNext、loading、重試預算和網路狀態;同一游標只允許一個請求。預取閾值應依內容高度和網路延遲調整,快速捲動時仍保留明確按鈕,避免觀察器連續觸發。
3. 處理回應、取消與失敗
回應必須確認請求游標仍是目前預期,舊請求晚到時丟棄或合併到已知集合。使用者離開頁面可取消未完成請求,但取消不應清除已顯示資料。失敗狀態顯示原因、重試按鈕和已載入數量;指數退避只用於自動重試並設定上限,避免服務端故障時形成請求風暴。
4. 建立可存取的替代路徑
哨兵不應成為唯一控制點。提供可聚焦的「載入更多」、明確的載入中和已到末端提示,使用語意清單、穩定標題層級和足夠的焦點可見性。長清單可提供分頁、跳過重複內容和「回到清單頂部」連結;焦點移動應有明確規則,不能因新節點插入把鍵盤使用者送到頁面末端。
5. 驗證效能、可用性與恢復
測試只用 Tab 和 Enter 完成多頁載入,檢查螢幕閱讀器能感知新增內容與失敗。用慢網、離線、快速捲動、重複點擊、返回前進、縮放 200% 和動態圖片高度測試。觀察請求數、重複率、首屏與每頁延遲、取消率和恢復成功率;長清單必要時採用虛擬化,並驗證虛擬化不會破壞語意和焦點。
高品質示範回答
我會把清單建立在穩定游標和項目 id 之上,客戶端記錄已消費游標、已見 id、進行中的請求和重試次數。哨兵進入預取區只發出一次載入訊號,回應必須符合目前游標,重複或亂序資料被去重。載入失敗顯示可聚焦的重試按鈕,離線時保留已載入內容。無限捲動旁邊提供「載入更多」、分頁或跳轉入口,確保鍵盤和螢幕閱讀器使用者不依賴滾輪;返回頁面時按項目 id 恢復位置。最後用慢網、離線、快速捲動、縮放、返回前進和螢幕閱讀器驗證。
常見錯誤
- 直接用頁碼拼接資料,忽略前方插入造成的重複和遺漏。
- 每次觀察器回呼都發請求,沒有游標去重和進行中鎖。
- 失敗後無限重試,或把重試按鈕做成不可聚焦的提示文字。
- 把捲動作為唯一導覽,使用者無法用鍵盤載入、分頁或回到頂部。
- 新內容插入後焦點跳到末尾,螢幕閱讀器使用者失去當前位置。
- 只測快速桌面網路,不測離線、縮放、動態高度和返回恢復。
追問及應對
為什麼不用頁碼分頁?
資料會新增或刪除時,頁碼邊界會移動。穩定排序加游標能減少重複和遺漏;若業務允許快照,也可用快照 token 明確同一次瀏覽的邊界。
哨兵觸發太早會浪費請求,怎麼調?
根據項目平均高度、捲動速度、網路延遲和取消率調整 root margin,並把它作為可觀測參數。預取仍應受 hasNext、並行鎖和預算約束。
新資料插入清單頂部時如何保持閱讀位置?
先記錄錨點項目及其相對偏移,再插入新節點並補償捲動偏移;對螢幕閱讀器和鍵盤使用者提供「有新內容」按鈕,由使用者決定何時跳轉。
何時應該改成分頁?
需要深連結、精確跳頁、搜尋結果可比較、清單很長或內容消費有明確段落時,分頁通常更可預測。可以保留漸進載入,但必須提供可見的分頁或載入更多入口。