「當文章超過 50 篇時,傳統的上下篇導航已經不夠用了。」
隨著 LeetCode 系列與 AI 專題的增加,使用者需要更直覺的方式在不同類別間跳轉。 我決定實作一個「全站導覽抽屜」與「動態目錄系統」。這不僅是 UI 的改變, 更是從硬編碼(Hardcoded)轉向配置驅動(Configuration-driven)的重大重構。
核心架構:單一數據源
為了避免每次新增文章都要修改多個地方,我建立了一個中心化的配置檔 config/blog.tsx。 所有的導航組件、搜尋引擎、甚至是首頁的文章清單,都從這個檔案讀取數據。
💡 優點:當我移動檔案目錄(如將文章歸類到 leetcode 資料夾)時,只需更新這裡的 href,全站導航就會自動同步。
實戰一:全站即時搜尋
懸浮導覽列中的搜尋框使用了雙層過濾演算法。它不僅過濾文章標題, 還會根據類別名稱進行匹配。
搜尋邏輯虛擬碼
- 使用者輸入關鍵字 (Query)
- 過濾 Series:
- 若 Series 標籤符合 Query → 保留該系列所有文章
- 若 Series 標籤不符 → 檢查該系列下的每一篇文章
- 過濾 Post:檢查標題或副標題是否包含 Query
- 重新封裝:只顯示有匹配結果的類別
實戰二:動態目錄與滾動追蹤
目錄 (Table of Contents) 必須具備兩個核心功能:自動提取標題與滾動高亮。
自動提取
使用 document.querySelectorAll('h2, h3')。 為了避免抓到頁首或頁尾,我們將範圍限制在 article 標籤內。
滾動追蹤
放棄監聽 scroll 事件(效能差),改用 IntersectionObserver。 當標題進入視窗頂部 20% 範圍時,觸發高亮。
效能與交互體驗優化
- ✨
佈局抖動防止
導覽列抽屜開啟時,會導致頁面滾動條消失,產生佈局跳動。 我使用了
HeroUI的Drawer組件,它會自動處理overflow: hidden與 padding 補償。 - 🎭
流暢過場動畫
使用
framer-motion的AnimatePresence。 當使用者在導覽列中切換類別時,文章清單會以微小的位移與淡入效果呈現,減少視覺疲勞。