Communitygithub.com

deputychinh/frontend

用於在 Vue 3 或 React 網頁應用程式中新增或修改使用者所見或所點擊的任何內容——畫面、元件、組合式函式/鉤子、狀態管理、表單、路由或資料請求——即使只是微調,或請求只提到「UI」、「頁面」、「表單」、「前端」或「按鈕沒反應」時使用。

frontend 是什麼?

此技能專注於 Vue 3 與 React 前端開發,為 AI 代理提供一套結構化的開發工作流程與最佳實踐規範。其核心目標是建立「對每位使用者、每種狀態都有效,且易於修改」的畫面。技能同時支援 Vue 3 與 React,並遵循專案既有的慣例(CLAUDE.md、文件約定與設計系統),絕不會覆寫它們。工作流程從載入專案慣例與盤點現有元件開始,接著要求撰寫「狀態表」以明確資料來源與所有畫面狀態(載入、空、錯誤、成功),然後先撰寫測試、在功能資料夾內建構程式碼、處理國際化與樣式,最後透過 Playwright 在真實瀏覽器中進行無障礙與鍵盤測試。此技能也列出了大量的反模式,並提供 Vue 與 React 各自與共通的明確禁止事項,確保輸出高品質、可維護且無障礙的程式碼。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/deputychinh/Skills/tree/HEAD/skills/frontend

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

frontend — 畫面要對每位使用者、每種狀態都有效,且易於修改

務必優先遵循儲存庫的 CLAUDE.md、docs/conventions.md 與 docs/design-system.md;此技能僅補足遺漏之處,絕不覆蓋它們。視覺相關工作(代碼變數、佈局、顏色、CSS)屬於 css-design;以使用者身分執行應用程式與最終驗證則屬於 verify-app。

選擇技術棧。 Vue 3 與 React 都是第一等公民,遵循相同規則。使用儲存庫既有的框架;若為新應用程式,則使用交付設定檔中的前端預設值(請參閱儲存庫 README),否則在分類階段詢問一次。Vue:TypeScript + Vite(npm create vue@latest -- --ts --router --pinia --vitest --playwright --eslint --prettier)並參考 references/vue-patterns.md。React:TypeScript + Vite(或儲存庫的 meta-framework)並參考 references/react-patterns.md。絕不在一個應用程式中混用框架。需要 SSR 或 SSG 以利 SEO?請在 ADR(architect)中記錄 Nuxt 或 Next.js;此技能涵蓋客戶端部分。

工作流程

  1. 載入儲存庫的慣例與庫存清單。 讀取 CLAUDE.md、docs/conventions.md、docs/design-system.md;列出可重複使用的部分(ls src/components src/features src/composables src/hooks src/stores)。檢測資料層、路由、表單與國際化函式庫(Vue:grep -E '"(@tanstack/vue-query|pinia|vue-router|vee-validate|vue-i18n)"' package.json;React:grep -E '"(@tanstack/react-query|@tanstack/react-router|react-router|react-hook-form|i18next|react-intl)"' package.json)。絕不添加第二個資料層、路由、狀態管理、表單或國際化函式庫。證據: 故事的筆記列出重複使用的元件與組合式函式/鉤子,以及任何新增的部分,並附上原因。
  2. 在撰寫程式碼之前撰寫狀態表。 針對每個視圖:每筆資料及其位置——伺服器(查詢)、URL(路由參數/搜尋)、共享客戶端(Pinia store、React context 或儲存庫的 store)、本地端(ref / useState)、衍生(computed / render 中的 const)、外部(包裝瀏覽器 API 的 composable 或 useSyncExternalStore)。然後列出四種狀態(載入、空、錯誤、成功)以及每種狀態的複製鍵。證據: 故事中的表格。
  3. 先撰寫會失敗的測試。 Vitest + @testing-library/vue 或 @testing-library/react、userEvent.setup()、按角色和可存取名稱查詢、每個測試一個行為、在服務邊界偽造網路(MSW 或儲存庫在 src/test-utils 中的假客戶端)。涵蓋每種狀態、鍵盤路徑和一個負面案例。證據: 運行顯示因正確原因而顯示紅色。
  4. 在功能資料夾內構建。 src/features/<name>/services(型別化的 API 呼叫,無框架)→ composables / hooks(包裝 useQuery/useMutation 和 key factory 的 useX)→ components(使用 <script setup lang="ts"> 的 Name.vue,或 Name.tsx)→ 組合它們的路由視圖。Props 與 events 有型別,無 any,無非空斷言 !,使用 @/ 匯入。證據: git diff --stat 保持在 feature 內,加上有意的共享更改。
  5. 複製與格式化。 每個可見文字字串都來自本地端檔案(vue-i18n 的 useI18n(),或 React 儲存庫的 i18n 函式庫或 copy module),且每個語言環境都有相同的鍵;測試會強制執行一致性。數字與日期透過 i18n 格式化器或 Intl。證據: 一致性測試通過;無硬編碼的複製,由 lint 強制執行(@intlify/vue-i18n/no-raw-text;React:react/jsx-no-literals 或 i18n 插件的規則)——引用 lint 的退出碼。
  6. 使用 css-design 設定樣式。 僅使用代碼變數,BEM 區塊 = 元件名稱,每種狀態都有樣式;.vue 樣式透過 postcss-html 進行 lint 檢查。證據: Stylelint 檢查通過。
  7. Stories(元件庫)。 每種狀態一個 story,兩個主題;Storybook 的 axe 檢查通過。證據: stories 測試與 axe 檢查通過。
  8. 閘道,由退出碼鏈接。 npm run lint && npm run type-check && npm run test:unit -- --run(Vue:vue-tsc --build;React:tsc -b),或 make ci;絕不透過 | tail 判斷。證據: 退出碼為 0 且覆蓋率達到或高於儲存庫閾值。
  9. 在真實瀏覽器中針對生產構建進行旅程測試。 npm run build 並提供輸出(vite preview,或儲存庫使用的靜態伺服器)。為主路徑新增或擴充 Playwright 規格,搭配 @axe-core/playwright(標籤 wcag2a wcag2aa wcag21aa wcag22aa,嚴重與關鍵 = 0)。擷取 docs/delivery/<slug>/evidence/<view>-390.png 與 -1280.png,如果應用程式有深色主題則加上。在引用之前先開啟每張截圖。證據: 規格通過,PNG 檔案存在。
  10. 鍵盤與螢幕閱讀器測試。 使用 Tab 鍵瀏覽新視圖:順序、可見焦點、Escape 鍵關閉覆蓋層且焦點返回觸發元素;導航後焦點落在新標題上且標題已變更。使用螢幕閱讀器(VoiceOver Cmd+F5,或 NVDA)抽查名稱與宣告。證據: 故事 QA 區段中的三行筆記。
  11. 移交。 執行 verify-app 進行端到端驗證;在 deliver-loop 中,獨立審查會對該項目進行評分。此處不重複其步驟。

核心檢查清單

  1. 不儲存可以衍生的內容:使用 computed(React:render 中的 const);沒有僅用於設定其他狀態的 watcher 或 effect。
  2. Watcher 與 effects 僅與外部同步(DOM API、訂閱、計時器、第三方小工具)並進行清理(onWatcherCleanup/onUnmounted;React:effect 的回傳值)。由使用者操作導致的工作在事件處理程式中執行。
  3. 伺服器資料永遠不會複製到本地狀態或 store 中;查詢鍵包含請求使用的所有輸入(在 Vue 中作為 ref 或 getter,以便變更時重新請求)。
  4. 使用者會分享或重新載入的選取、篩選器、標籤頁與分頁,應存在於 URL 查詢中。
  5. 每個資料視圖都呈現載入、空、錯誤(含重試)與成功狀態;測試涵蓋全部四種。
  6. 每個輸入都有可見的 <label for>(兩個框架都使用 useId() 產生的 ID);錯誤是透過 aria-describedby 關聯的文字,輸入內容會保留,提交時焦點移動到第一個無效欄位。
  7. 優先使用原生元素(button、a href/router link、dialog、details、input type);不使用 div @click / div onClick。
  8. 自訂小工具遵循相符的 WAI-ARIA APG 模式,包含鍵盤操作。
  9. 不會移動焦點的非同步結果,透過一個只渲染一次且為空的 role="status"/role="alert" 區域來宣告(Vue:teleport 到 body;React:portal,如果它必須比視圖存活更久)。
  10. 路由變更:更新 document.title 並將焦點移動到頁面的 h1 或 main(Vue:router.afterEach + template ref;React:router 的對應方式)。
  11. 錯誤在每個路由和每個有風險的小工具層級被捕獲(Vue:onErrorCaptured 邊界元件;React:error boundary)並顯示重試,絕不顯示空白頁面。
  12. 無硬編碼的顯示字串;每個語言環境都有相同的鍵。
  13. 測試按角色/標籤/文字查詢、與 user-event 互動,且絕不斷言類別名稱、元件內部(wrapper.vm、狀態值)或 composable/hook 呼叫。
  14. 沒有 v-html / dangerouslySetInnerHTML,除非在使用前立即使用 DOMPurify 進行消毒;來自資料的 URL 被列入白名單為 https:/mailto:/相對路徑。
  15. shallowRef/markRaw/v-memo/KeepAlive(React:memo/useMemo/useCallback)僅在有效能分析測量或已記錄的需求時使用。
  16. 圖表與資料視覺化具有可存取名稱與摘要、資料表(或文字)替代方案、色盲安全調色板且系列也能透過標籤、形狀或圖案區分,以及對任何互動的鍵盤存取——無論儲存庫使用哪種圖表庫。

反模式

Vue:

  • watch(items, v => { filtered.value = v.filter(...) })——請使用 computed。
  • const { count } = reactive(state) 或 const { name } = store——反應性會遺失;請使用 toRefs / storeToRefs,或偏好 ref。
  • watch(props.id, ...) 或將解構的 prop 傳遞給 composable——請傳遞一個 getter () => id。
  • 變動 prop 或 useQuery 的資料;將查詢資料直接綁定到 v-model——請複製到表單中。
  • 在同一個元素上使用 v-if 和 v-for;在可重新排序的清單上使用 :key="index"。
  • 在 composable 中,在 onWatcherCleanup 或註冊生命週期鉤子之前使用 await。
  • 為路由元件使用 defineAsyncComponent(路由直接接受 () => import(...))。
  • 在導航守衛中使用 next()——請回傳 false、一個位置,或不回傳任何內容。
  • 測試中存取 wrapper.vm 或呼叫 setData。

React:

  • useEffect(() => setFiltered(items.filter(...)), [items])——請在 render 中計算。
  • 當 id 變更時,在 effect 中重置表單——請傳遞 key={id}。
  • 在條件式或迴圈中呼叫鉤子;就地變動狀態而非取代。
  • 在可重新排序的清單上使用 key={index};每次 render 都將新的物件或函式 prop 傳遞給一個因測量原因而被 memo 化的子元件。

兩者共通:

  • 在掛載時進行請求,沒有取消、快取、重試或錯誤分支——請使用資料層。
  • 只有 spinner,沒有空或錯誤分支;錯誤被 console.log 吞掉。
  • staleTime 為 0 的資料每天變更,導致每次聚焦都重新請求。
  • 樂觀更新沒有快照、回滾和完成後使快取失效。
  • 佔位符用作標籤;僅用顏色標記錯誤;role="button" 沒有按鍵處理。
  • 到處使用 getByTestId;整個頁面的快照;測試實作細節。
  • 一個功能 barrel 檔將所有內容拉入第一個路由 chunk。
  • :href="user.url" / href={user.url} 沒有檢查協定。

「完成」前的證據

  • 針對每種狀態與鍵盤路徑的先失敗後通過的單元測試。
  • Lint、vue-tsc 或 tsc、測試鏈接,退出碼 0;覆蓋率達到或高於閾值。
  • 針對生產構建的 Playwright 旅程測試,axe 嚴重/關鍵 = 0。
  • docs/delivery/<slug>/evidence/ 中的 390 與 1280 像素截圖(以及深色主題),每張都已開啟。
  • 故事 QA 區段中的鍵盤與螢幕閱讀器筆記。
  • 然後執行 verify-app。

參考資料

  • references/vue-patterns.md — Vue 檢查清單:SFC 與元件 API、反應性陷阱、computed vs watch、composables、Pinia、Vue 的 TanStack Query、Vue Router(URL 狀態、守衛、焦點)、表單、i18n、無障礙細節、效能、安全性、工具;每個項目都有來源。
  • references/react-patterns.md — React 檢查清單:相同主題,加上靜態匯出(Next.js / Nuxt generate)變體。
  • references/a11y-and-testing.md — UI 程式碼的 WCAG 2.2 AA 項目、ARIA/APG、鍵盤與即時區域、圖表、Vue 與 React 的 Testing Library、MSW、Playwright + axe、不該測試的內容。

相關技能