具代表性的面試主題

前端面試:SPA 路由切換後如何管理焦點?

前端困難
OfferCC 編輯團隊發佈 更新

題幹

一個客戶端渲染的電商 SPA 會保留頁首和側邊欄,只替換主要內容。導覽後,鍵盤和螢幕閱讀器使用者可能仍停在舊觸發控制項,或失去新頁面的上下文。路由會非同步載入,導覽可能被替換,篩選條件會修改 URL 但不開始新任務,上一頁與下一頁還應還原有用的上下文。請設計焦點、播報、競態處理、歷史還原和測試策略。

問題與使用情境

完整頁面導覽會替換文件及其標題。SPA 軟導覽繼續使用同一份文件,焦點可能留在一個周圍內容已消失的連結上。螢幕閱讀器使用者可能不知道新的商品頁、結帳步驟或錯誤頁已經就緒。

策略需要區分五類變化:首次載入、使用者發起的新路由、目前任務內的篩選或排序、被替換或取消的導覽,以及瀏覽器上一頁/下一頁。它還要與對話框等元件自己的焦點協議共存。目標是提供可預測的上下文,而非每次 URL 變化都移動焦點。

面試官考察什麼

面試官首先看候選人能否建立語意決策模型。「每次路由變化都聚焦標題」看似無障礙,卻會破壞篩選、錨點變化、首次 hydration 和歷史還原。強回答先判斷使用者的任務是否改變。

其次是瀏覽器基礎:tabIndex={-1} 可讓標題接收程式化焦點,又不會把它加入依序 Tab 路徑;focus() 預設可能捲動元素;preventScroll 能拆分焦點還原與捲動還原;正數 tabindex 會製造脆弱的焦點順序。

最後是並行處理。如果路由 B 比 C 更晚完成,B 不能改回標題或搶走焦點。自動化能驗證作用中元素、標題和順序,卻不能證明每一種瀏覽器與輔助技術組合會如何播報。

回答前的釐清問題

  • 哪些變化會開始新任務? 從商品頁進入結帳是新任務,調整排序通常不是。這決定焦點移動或留在觸發控制項。
  • 何時算路由提交完成? 只在勝出的路由已渲染最終主標題後聚焦,不在點擊、URL 變化或骨架畫面出現時執行。
  • 浮層由誰管理? 對話框負責自己的初始焦點、焦點限制和關閉後還原;路由策略不能與它競爭。
  • 歷史記錄要還原什麼? 明確每個歷史項目還原焦點、捲動位置或兩者。兩者必須協調,避免連續跳動。
  • 支援哪些瀏覽器和輔助技術? 播報行為存在差異,發布測試矩陣必須明確。
  • 每個路由能否提供描述性標題和唯一主標題? 把它們設為路由契約;main 地標只作受控降級。

30 秒回答框架

「我先對導覽分類,再決定是否移動焦點。首次載入不強制聚焦。使用者發起的新任務路由只有在最終提交後才更新文件標題,並聚焦設定了 tabIndex=-1 的描述性 H1。同一任務內的篩選保留觸發控制項,透過持久的禮貌狀態區播報完成結果。每次導覽都有權杖,只有最新且已提交的路由能修改標題和焦點。上一頁/下一頁優先還原該歷史項目保存的有效語意目標,否則退回 H1,並與捲動還原協調。測試涵蓋首次載入、快速連續導覽、錯誤、篩選、歷史、鍵盤順序、可見焦點及真實螢幕閱讀器。」

分步深入分析

先建立轉換決策表:

轉換焦點動作播報方式
首次載入或 hydration不強制移動使用原生文件與標題行為
PUSH 到新任務聚焦已提交路由的 H1更新標題並聚焦標題
同任務篩選、排序、分頁保留觸發控制項必要時禮貌播報結果或狀態
上一頁/下一頁 POP還原有效目標,否則 H1還原上下文或聚焦標題
重新導向或錯誤路由聚焦該路由最終 H1使用最終標題和主標題
對話框開啟或關閉交給對話框協議對話框名稱與返回目標

路由契約提供最終文件標題、描述性 H1 引用和語意路由鍵。H1 使用 tabIndex={-1},可被程式聚焦但不增加一個 Tab 停靠點,並保留清晰的焦點樣式。跳過導覽連結仍應是第一個可聚焦控制項並指向 main;它解決重複導覽略過問題,與路由焦點並不衝突。

焦點動作屬於提交邊界。為每次導覽嘗試分配遞增權杖。資料和介面完成後,僅當權杖仍為目前值且 H1 已掛載時才執行副作用。不要依賴固定延遲,網路和渲染速度會讓它產生競態。

text
beginNavigation(kind):
  token = nextToken()
  rememberCurrentFocus(historyEntryKey)

commitRoute(token, kind, title, heading):
  if token != currentToken or heading is not connected:
    return
  document.title = title
  if kind is PUSH or semantic-task REPLACE:
    heading.focus()
  else if kind is POP:
    focus(validSavedTarget(historyEntryKey) or heading)

保存穩定的路由內焦點 ID,不保存自動產生的 CSS 路徑。POP 時只還原仍存在、可見、可用且在還原狀態中有意義的元素,否則聚焦 H1。若路由器獨立還原捲動位置,可使用 focus({ preventScroll: true }) 後只還原一次捲動;一般 PUSH 通常讓聚焦自然顯示 H1 更清楚。

避免重複播報。先更新標題再聚焦新 H1,通常已提供足夠上下文,但具體語音取決於輔助技術。預設不要再用即時區域重複同一標題。篩選操作保留焦點時,可用持久的 role="status" 或 aria-live="polite" 播報最終結果數。assertive 可能中斷目前語音,只用於真正緊急的資訊。

測試判定應直接來自策略:首次 hydration 不能搶焦點;PUSH 最終提交後,document.activeElement 是新 H1、標題已更新,下一次 Tab 到達第一個合乎邏輯的互動控制項;篩選後觸發控制項仍有焦點,狀態只更新一次;A→B→C 競態中即使 B 最後完成,C 仍擁有標題和焦點;錯誤與重新導向聚焦各自標題;POP 還原有效目標或確定性降級。

自動化涵蓋上述 DOM 斷言、目標卸載、縮放及減少動態效果版面。隨後用鍵盤和支援矩陣中的真實組合手動測試,例如 VoiceOver/Safari,以及 NVDA 或 JAWS 與支援的瀏覽器。核對焦點可見、順序合理、捲動不突兀、播報可理解,並記錄版本,因為語音結果是整合行為,不是單靠 DOM 就能保證的結果。

高品質範例回答

「我會把焦點行為納入路由的語意契約。每個路由提供最終文件標題和描述性 H1 引用。首次 hydration 不移動焦點;使用者發起且改變任務的 PUSH 在最終提交後聚焦 H1;篩選和排序保留觸發控制項;POP 優先還原穩定的歷史目標,失敗時退回 H1。

H1 使用 tabIndex=-1,因此能被程式化聚焦而不會增加 Tab 停靠點。我保留可見焦點樣式和指向 main 的跳過導覽連結。標題和焦點只在勝出的路由提交後一起更新。每次導覽有一個權杖,過期非同步結果會被忽略,取消的路由就無法搶焦點。

歷史項目保存路由內語意焦點 ID,只還原已連接、可見且可用的目標。若捲動單獨還原,則用 preventScroll 聚焦後只處理一次捲動。同任務非同步更新使用持久的禮貌狀態區;不會在標題和即時區域重複播報路由名稱。

自動化驗證作用中元素、標題、Tab 順序、篩選保留、A→B→C 快速導覽、重新導向、錯誤和 POP 降級。最後用支援的鍵盤與螢幕閱讀器矩陣驗證真實語音、焦點樣式和捲動。這樣能區分確定的 DOM 行為與必須實際觀察的輔助技術行為。」

常見錯誤

  • 每次 URL 變化都聚焦 → 篩選和錨點變化打斷目前任務 → 先按語意分類。
  • 點擊連結時立即聚焦 → 目標可能尚不存在或被取消 → 只處理勝出的已提交路由。
  • 使用固定延遲 → 不同渲染速度產生競態 → 使用路由生命週期和導覽權杖。
  • 聚焦 body 或使用正數 tabindex → 上下文和順序不明確 → 聚焦設定 tabIndex=-1 的描述性 H1。
  • POP 總是跳到 H1 → 上一頁會遺失使用者位置 → 還原有效歷史目標並提供確定性降級。
  • 重複播報標題 → 使用者聽到冗餘語音 → 路由優先用聚焦標題,同頁更新才用狀態區。
  • 把自動掃描當成驗收 → 掃描無法驗證真實語音 → 加入鍵盤和輔助技術手動測試。

追問與回答

追問 1:為什麼不總是聚焦 main 地標?

H1 通常能更具體地命名新任務。路由無法提供標題時,main 可作為降級,但要求每個路由提供主標題能同時改善可見結構、文件層級和可測試性。

追問 2:滑鼠點擊導覽後也要移動焦點嗎?

使用者操作替換主要任務時,一致的上下文對不同輸入方式都有價值,包括會點擊的螢幕閱讀器使用者。應根據語意導覽決策,不要猜測使用者是否只用鍵盤。背景重新整理不能移動焦點。

追問 3:快速導覽時 B 比 C 更晚完成怎麼辦?

B 的權杖已不是目前值,其提交副作用直接返回,不能修改標題、焦點或狀態。中止 B 的請求可以節省資源,但取消可能太晚或不受支援,因此仍需權杖檢查。

追問 4:焦點還原和捲動還原如何配合?

一般 focus() 可能把目標捲動到視窗。POP 若由路由器還原保存的捲動位置,就用 preventScroll 驗證並聚焦目標,再執行一次捲動還原。只能有一個明確的捲動所有者。

追問 5:什麼時候使用 assertive 即時區域?

僅在延遲聽到會造成嚴重問題時使用,例如緊急工作階段或安全訊息。結果數量和完成狀態使用 polite。路由上下文通常由最終標題和聚焦 H1 提供,避免第二次播報。

追問 6:做到這些就符合 WCAG 嗎?

不能單憑這一項下結論。該策略有助於動態應用程式維持可理解的焦點順序和上下文,完整符合性還取決於語意、名稱、鍵盤操作、對比度、錯誤處理等要求,應按產品目標檢查完整使用者旅程。

公開來源

同類題目