HanC's Blog

善用6個Clean Code技巧寫Vue.js

Posted:23rd December 2024
9 Minutes
1683 Words

前言

在當今的前端開發領域,Vue.js 是極受歡迎的框架之一。其簡潔的語法和強大功能使得開發者能夠快速構建可維護、可擴展的應用。然而,隨著項目規模擴大,維護性和可讀性常常成為挑戰。此時,清晰、簡潔、易讀的代碼結構就顯得尤為重要。

這篇文章將分享幾個運用「Clean Code」的技巧來提升Vue.js開發質量。這些技巧不僅能幫助工程師寫出更高效、易於維護的代碼,還能提高團隊合作效率,讓代碼更具可讀性和可理解性,從而在長期開發過程中減少技術負擔、降低錯誤風險。

1. 使用Composition API(組合式 API)編寫程式

傳統的 Options API 元件,相信寫過Vue的大家都不陌生,在編寫小專案或剛起步時,可能會覺得這架構還不錯,變數在同一塊、函式在同一塊,但當專案架構開始變大時,使用的變數及函式越來越多,此時會漸漸覺得每次要找某一個相關聯的變數 & 函式時,它們好像散落在遠方。

Composition API 就可以做到「功能切割」,將同一功能相關的內容都集中在一個區塊,提高可讀性 及 維護性。

2. 遵守 Vue 命名規則

  • 大駝峰 (PascalCase)
    • 用於元件檔案名稱,應為多個單詞組合而成
    • 可使用於 template 中,無底線,ex. LoginModal
    • props中變數命名
    1
    props: {
    2
    welcomeMessage: {
    3
    type: String,
    4
    default: '歡迎來到網站'
    5
    }
    6
    }
  • 烤串命名 (kebab-case)
    • 可使用於 template 中,全使用橫線連接,ex. login-modal
    • 父元素代入值至子元件時,需使用橫線連接
    1
    <ChildComponent :welcome-message="嗨嗨" />

3. 多使用複用元件 及 搭配 Slot

‘複製’ & ‘貼上’,應是工程師做起來最舒暢的事情,當對一個專案越來越熟悉,一旦有新需求、新元件需要製作時,第一直覺會開始搜尋腦中資料庫,思考以前有沒有做過類似的功能和元件,找到後就會很快樂的複製貼上,再稍微小改一下符合需求。

以前的我的確也會這樣,只想在短時間內達成目的就好,但發現專案越來越大時,若需求改動頻率高,且同樣的代碼於不同頁出現的次數過高,對於維護者而言是滿滿的技術債。 幸好曾踩過這樣的坑,便養成非必要時,同質性極高的功能,能組合成元件複用,盡可能製成元件。

於Vue中製作元件,可採用slot 提昇其彈性,亦可於複用元件中,寫入document,以表明其用途,以下為一複用卡片元件實例:

Card.vue
1
<template>
2
<div class="card">
3
<!-- Slot for the card header -->
4
<header class="card-header">
5
<slot name="header">我是標頭~</slot>
6
</header>
7
8
<!-- Slot for the card body -->
9
<main main class="card-body">
10
<slot name="body">最亮眼的卡片~</slot>
11
</main>
12
13
<!-- Slot for the card footer -->
14
<footer class="card-footer">
53 collapsed lines
15
<slot name="footer">地基是我</slot>
16
</footer>
17
</div>
18
</template>
19
20
<script lang="ts">
21
/**
22
* Card Component
23
*
24
* This component provides a flexible layout using named slots for the header, body, and footer sections.
25
*
26
* ## Usage:
27
*
28
* ```vue
29
* <Card>
30
* <template #header>
31
* <h1>客製化標頭</h1>
32
* </template>
33
* <template #body>
34
* <p>卡片內容寫於此</p>
35
* </template>
36
* <template #footer>
37
* <button>點我點我</button>
38
* </template>
39
* </Card>
40
* ```
41
*
42
* ## Slots:
43
* - `header`: Slot for the card's header content (optional, defaults to "Default Header").
44
* - `body`: Slot for the card's main content (optional, defaults to "Default Body").
45
* - `footer`: Slot for the card's footer content (optional, defaults to "Default Footer").
46
*/
47
export default {
48
name: 'Card',
49
};
50
</script>
51
52
<style scoped>
53
.card {
54
border: 1px solid #ddd;
55
border-radius: 8px;
56
overflow: hidden;
57
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
58
}
59
.card-header,
60
.card-footer {
61
padding: 1em;
62
background-color: #f5f5f5;
63
}
64
.card-body {
65
padding: 1em;
66
}
67
</style>

4. 利用Composable,將共用邏輯抽出函式

與製作複用組件同樣的觀念,能不重複寫,盡可能抽出、封裝,使狀態與功能便於管理,當分析出接下來要開發的功能會重複使用於此專案,即可利用Composable函式,寫入共用邏輯,以減少重複的代碼。例如像時間轉換功能,於論壇內可能會需要顯示’剛剛’、‘2小時前’、‘昨天’、‘2024-11-29’…等非正規化的時間格式,因此可編寫複用函式,並於多個地方引入使用。

重點項:

  • 文件名應以 use 開頭,例如 useContentWidthControl.ts
  • Composable函式約定用PascalCase命名,並以”use”作為開頭,例如 useLinkList()
  • 一定要於setup()<script setup> 中使用,否則程式會報錯誤,就算Composable的函式還有包其它的Composable函式,也務必於function內進行引用。

5. 使用Lint維持代碼品質

  • ESLint & Prettier是編寫Code時的好夥伴,於團隊中協作時,每一位工程師多少會有自己的編寫習慣,例如雙引號 or 單引號、兩個空白為縮排 or 四個空白為縮排。一個專案除了邏輯上正確、精簡外,代碼的格式化也很重要,否則在維護、閱讀上會需要多花時間理解,可能還會造成誤解。
  • 也可將Linting加入CI/CD流程中,使之自動化檢測 & code review
  • 而之前會常常遇到CI/CD時,因Linter沒通過而無法deploy新commit,因此找了自動化檢復的工具 - 搭配Husky。可於每次提交代碼前,自動執行檢查 & 修復。
    • pnpm install husky
    • 配置 package.json,scripts:"prepare": "husky install"
    • $ pnpm prepare
    • 於.husky資料夾下新增pre-commit檔案,貼上以下內容:
    1
    #!/usr/bin/env sh
    2
    . "$(dirname -- "$0")/_/husky.sh"
    3
    4
    npx lint-staged
    • 接下來於每次commit時,系統即會採用.eslintrc.js配置的標準進行檢查

6. 保持Template簡潔

  • 避免使用過於複雜的邏輯判斷於Template中,可免除將js & 網頁架構太常混雜一起,降低閱讀性,於後續的維護中即可於同一區塊進行更新。
  • 若不將邏輯判斷寫於Template中,即可善用Computed方法,創建易可理解的函式名,納入邏輯判斷,也可重複使用此函式於多個地方。

不佳範例:

1
<template>
2
<div
3
v-if="isLogin && !isManageOn && !hasFirstFloor"
4
class="lg:hidden mt-4 py-5 border-y border-solid border-mean"
5
:class="
6
floorDataList.list.length === 1 &&
7
floorDataList.list[0].isFavorite
8
? 'border-b-black'
9
: ''
10
"
11
>
12
<ToggleBtn />
13
</div>
14
</template>

修正後範例:

1
<script>
2
const isShowToggleBtnBlock = computed(() => {
3
return !isLogin.value && !isManageOn.value && !hasFirstFloor.value
4
})
5
6
const bottomBorderStyle = computed(() =>
7
data.list.length === 1 && data.list[0].isFavorite ? 'border-b-black' : '')
8
</script>
9
10
<template>
11
<div
12
v-if="isShowToggleBtnBlock"
13
class="lg:hidden mt-4 py-5 border-y border-solid border-mean"
14
:class="bottomBorderStyle"
15
>
3 collapsed lines
16
<ToggleBtn />
17
</div>
18
</template>

結語

以上是看過網路上其它人分享的文章後,篩選出自己其實滿需要的幾個要點,以及經歷過的一些專案經驗,再與大家分享,希望上述內容對讀者有所幫助。

Article title:善用6個Clean Code技巧寫Vue.js
Article author:HanC
Release time:23rd December 2024