iT邦幫忙

2026 iThome 鐵人賽

DAY 20
0
Modern Web

一個活了六年的 Vue 2 後台,升級到 Vue 3 的那兩年系列 第 20

Day 20|框架送你一台咖啡機,團隊自己買了三個濾杯

  • 分享至 

  • xImage
  •  

模組四|核心系統改寫(Day 17–21)

Day 9 我丟過一個數字:框架附了一整套表格機制(用一份設定物件描述整張表格,也就是 schema 化那一套),43 個檔案、5,832 行,而我們的業務頁面用了 1 次,而且那一次還是框架自帶的錯誤紀錄頁。

今天把這件事講完:既然框架給的沒在用,那 162 個表格頁面到底用什麼?

答案是三個自己寫的 hook,合計被使用 149 次。

先講真正拿到的收益

換掉 UI 元件庫最大的收穫,不是畫面變好看,是表格欄位的定義方式變了

舊系統是用子標籤宣告欄位:一個表格有幾欄,就寫幾個標籤。Day 2 數過,全專案 3,354 個。

新系統是給一個陣列:

const columns = [
  { title: '訂單編號', dataIndex: 'orderNo', width: 180 },
  { title: '金額', dataIndex: 'amount', align: 'right' },
]

差別在哪?欄位定義從「模板」變成「資料」之後,它就可以被程式操作了。

// 依權限過濾欄位 → 就是陣列操作
const columns = allColumns.filter(col => hasPermission(col.auth))

// 加上排序能力 → 就是一個函式
const columns = withSorter(baseColumns, ['amount', 'createdAt'])

在舊系統,這兩件事都要在模板裡加 v-if、在每個表格重複一次。

這是換元件庫真正付錢買到的東西,而且它是框架設計本身帶來的,不是我們的功勞。

但框架給的「完整表格元件」,我們沒用

框架不只給了「欄位是資料」這個能力,它還給了一整套:一個包好的表格元件,你把設定丟進去,它幫你處理分頁、載入狀態、工具列、欄位設定、拖曳排序。

43 個檔案、5,832 行。而業務頁面用了 1 次。

那 162 個有表格的業務頁面在做什麼?直接寫元件庫的基礎表格標籤,然後自己組。

我們自己寫了三個 hook

團隊實際採用的抽象長這樣——三個小 hook,各做一件事:

自寫的 hook 被使用次數 它解決什麼
欄位排序 96 每個表格都要做排序,而每個人做法不同
捲動行為 43 換頁後捲軸位置該不該重置
虛擬捲動 10 資料量大時只渲染看得見的部分

合計 149 次。

它們的共同點是:每一個都只做一件事,而且不要求你改變寫表格的方式。

你的表格照原本的寫,只是排序那段呼叫這個 hook。

為什麼小的贏了大的

Day 9 我給過一個結論,這裡有更完整的證據:

一個抽象會不會被採用,跟它多完整無關,跟它要求使用者改變多少有關。

用一個場景:

有人送你一台全自動咖啡機。磨豆、萃取、打奶泡、保溫全包,還能記住你的偏好。

但你要用它,得先學它的操作面板、用它指定的豆子粗細、照它的流程走。而它做不到的事(例如你想試某種特殊沖法),你完全沒辦法插手。

於是你最後還是用手沖——只是買了三個好用的濾杯。

咖啡機沒有比較差。它只是要求你整套照它的方式來,而你的需求裡有兩成它處理不了。

那台咖啡機就是那 5,832 行。而三個濾杯是那 149 次。

這個對比 Day 7 出現過:mixin 和 composable,「繼承一整棟房子 vs 買樂高」。這是同一件事在元件層級的重演:

  • 大元件 = 你要嘛全接受,要嘛不用
  • 小 hook = 你要什麼拿什麼,不要的不用碰

而團隊在沒有人下指令的情況下,自然選擇了後者。這種「大家自然而然這樣做」的證據,比任何架構決策文件都可靠。

一個小紀律,落地了 397 次

我在每一個空格上都壓一顆倒扣的棋,於是漏掉的那一格一眼就跳出來

團隊有一條慣例:表格欄位沒有資料時,顯示 --,不要留空白。

理由很實際:空白會讓人分不出「這個欄位沒資料」和「這個欄位還沒載入」,也分不出「後端沒回這個欄位」和「後端回了空字串」。

我去數了一下,這個 -- 在業務頁面出現了 397 次。

這代表這條慣例是真的被執行的,不是寫在文件裡好看的。

而它能落地的原因我認為有兩個:

  1. 它夠小。 一條規則、一個符號,沒有任何理解成本。
  2. 它會被 review 抓到。 空白和 -- 的差別,在畫面上一眼就看得出來。

對照 Day 15 那個「命名規範訂了但有漏網」的狀況:規則能不能落地,跟它有多正確無關,跟它「違反時容不容易被發現」有關。

虛擬捲動:有些問題不是效能調校能解的

我不再把整卷攤開,只從兩根軸之間拉出一個手掌寬的視窗

最後這個不一樣:它真的動到了渲染策略。

舊系統有幾個報表頁,一次撈幾千筆資料,然後整個畫面卡住好幾秒。

當時的處理就是常見那幾招:減少欄位、加上分頁、限制查詢範圍。這些都有幫助,但沒有解決根本問題,因為問題不在資料量,在瀏覽器要一次建立幾千列的 DOM 元素。

新系統對這類頁面改用虛擬捲動:只渲染畫面上看得見的那二十幾列,捲動的時候動態替換內容。

團隊為此自己寫了一個元件(153 行),目前用在少數幾個真的需要的頁面上。

技術本身 153 行,沒什麼好講。值得記的是它示範的判斷:

當你已經把能調的都調了、還是很慢,那通常代表你在解錯的問題。

減少欄位是在「讓要做的事變少」,虛擬捲動是「改變做事的方式」。前者有天花板,後者沒有。

代價

一、自己寫 hook,代表框架升級的好處你拿不到。 框架那 5,832 行是有人維護、會修 bug、會加功能的。我們那三個 hook 出問題只能自己修。這是選擇「不接受框架抽象」的固定成本。

二、三個 hook 之間沒有統一的架構。 它們是不同時間、為了不同痛點寫出來的,彼此沒有共同的設計。目前規模還好,但如果長到十個,可能會出現「這件事該用哪個 hook」的問題,也就是 Day 18 那個「兩個入口」問題(同一件事有兩種寫法都通,每個人都得先猜哪個才是慣例)的預備狀態。

三、那 43 個檔案還躺在專案裡。 它們是框架的一部分,我們沒有刪(刪了怕影響其他東西),但業務頁面幾乎不用。這是一批「用不到但也不敢刪」的程式碼,跟 Day 4 那 8 個沒人用的全域掛載,性質完全一樣,只是規模大了一百倍。

第三點寫出來我自己也有點刺痛。我們花了一整篇批評舊系統留著沒人用的東西,然後在新系統留下了 5,832 行。

帶走什麼

  1. 「欄位定義從模板變成資料」比「換標籤名」重要得多。 前者讓你可以過濾、排序、共用;後者只是換一件衣服。
  2. 抽象的採用率,取決於它要求使用者改變多少。 完整但要求整套照做的方案,會輸給不完整但零成本接上的小工具。
  3. 能落地的規則,特徵是「違反時一眼看得出來」。 那個 397 次的 -- 就是靠這個活下來的。
  4. 調到極限還是慢,通常代表你在解錯的問題。 減少工作量有天花板,改變做事方式沒有。
  5. 不用框架的抽象,要承擔它的維護成本;用了框架的抽象,要承擔它的限制。 沒有免費的選項——但至少要知道自己選了哪一邊。

明天 Day 21 是模組四的最後一天,也是我覺得最難寫的一篇:表單為什麼沒有跟表格一樣被收斂? Day 9 給過一個很難看的數字:新系統的表單標籤比舊系統還多。我會論證為什麼那是對的,然後承認它也可能只是體面的說法。


上一篇
Day 19|一個 182 行的檔案,決定了全站每一次請求的命運
下一篇
Day 21|一個叫「表單項」的 hook,寫完之後零次使用
系列文
一個活了六年的 Vue 2 後台,升級到 Vue 3 的那兩年21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言