Vue3 Options API(傳統寫法) – Props 完全指南
簡介
在 Vue3 中,Props 是父層與子層之間傳遞資料的唯一官方管道。即使在使用 Composition API 時,Props 的概念依舊不變;但在 Options API(傳統寫法)下,如何宣告、驗證與使用 Props 仍是每位 Vue 開發者必須熟悉的基礎。正確的 Props 設計不僅能提升元件的可重用性,還能避免不必要的錯誤與效能問題。
本篇文章將從 什麼是 Props、如何在 Options API 中定義與使用,到 常見陷阱與最佳實踐,提供完整、實務導向的教學,適合剛踏入 Vue3 的新手以及想鞏固概念的中級開發者。
核心概念
1. 為什麼需要 Props?
- 單向資料流:父層資料只能由上而下傳遞給子層,子層不應直接改變父層的資料,這樣可以避免資料同步的混亂。
- 元件解耦:子元件只關心自己的 UI 與行為,透過 Props 接收外部資料,使元件更易於測試與重用。
2. 在 Options API 中宣告 Props
在 Options API 中,Props 透過 props 選項宣告,支援兩種寫法:
| 寫法 | 說明 |
|---|---|
| 陣列寫法 | 只列出 prop 名稱,類型與預設值皆為 any。 |
| 物件寫法 | 可同時設定類型、預設值、必填、驗證函式等。 |
// MyButton.vue
export default {
name: 'MyButton',
// 陣列寫法
// props: ['label', 'disabled'],
// 物件寫法(較常使用)
props: {
// 類型驗證 + 必填
label: {
type: String,
required: true
},
// 預設值 + 類型驗證
disabled: {
type: Boolean,
default: false
}
},
// 其他 Options...
}
小技巧:若只需要簡單傳值,陣列寫法即可;若想加入驗證或預設值,請使用物件寫法。
3. 預設值與類型驗證
3.1 基本類型
props: {
count: Number, // 類型為 Number,預設為 undefined
title: String, // 類型為 String
isActive: Boolean // 類型為 Boolean
}
3.2 使用 default 提供預設值
注意:
default只能是靜態值或返回值的函式(當預設值為物件或陣列時必須使用函式返回,以避免所有實例共享同一個引用)。
props: {
// 靜態預設值
size: {
type: String,
default: 'medium' // 若父層未傳入 size,預設為 'medium'
},
// 物件預設值(必須使用函式返回)
config: {
type: Object,
default: () => ({
color: 'blue',
rounded: true
})
}
}
3.3 多型別(Array of Types)
props: {
// 接受 String 或 Number
value: {
type: [String, Number],
required: true
}
}
4. 單向資料流與 .sync 修飾符
在 Options API 中,子元件 不應直接改變 傳入的 Props;若需要回傳變更,必須透過自訂事件($emit)告訴父層。
// Child.vue
export default {
props: {
modelValue: {
type: Number,
required: true
}
},
methods: {
increase() {
// 正確做法:emit 事件讓父層自行更新
this.$emit('update:modelValue', this.modelValue + 1)
}
}
}
父層使用 .sync(Vue3 已改為 v-model):
<!-- Parent.vue -->
<Child :modelValue="counter" @update:modelValue="counter = $event" />
提醒:
.sync已在 Vue3 中被v-model取代,但在 Options API 中仍可看到.sync的寫法,建議直接使用v-model以保持一致性。
5. 動態 Props 與 v-bind
有時候 Props 需要根據條件或資料變化動態傳入,v-bind(縮寫 :)提供了便利的寫法。
<!-- Parent.vue -->
<template>
<MyCard
:title="cardTitle"
:size="isLarge ? 'large' : 'small'"
v-bind="extraProps" <!-- 展開額外的 props 物件 -->
/>
</template>
<script>
export default {
data() {
return {
cardTitle: '歡迎使用 Vue3',
isLarge: true,
extraProps: {
elevation: 3,
rounded: true
}
}
}
}
</script>
6. 自訂驗證函式
有時候內建的類型驗證不足以滿足需求,這時可以使用 validator 自訂驗證邏輯。
props: {
email: {
type: String,
required: true,
validator(value) {
// 簡易的 Email 正則驗證
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
}
}
}
若驗證失敗,Vue 會在開發環境的 console 中顯示警告,幫助開發者快速定位問題。
常見陷阱與最佳實踐
| 陷阱 | 說明 | 解決方式 |
|---|---|---|
| 直接改變 Props | 在子元件內直接 this.prop = newValue 會觸發 Vue 警告,且破壞單向資料流。 |
使用 $emit 或 v-model 讓父層更新。 |
| 預設值共用參考 | 物件或陣列預設值直接寫在 default: {},所有實例會共享同一個引用。 |
使用函式返回 default: () => ({})。 |
忘記 required |
若必填的 prop 沒有傳入,會在 console 中出現警告,但 UI 可能因為 undefined 而崩潰。 | 明確設定 required: true,並在父層確保傳值。 |
過度使用 .sync |
.sync 會讓子元件「看起來」能改變 prop,實際上仍是事件機制,容易混淆。 |
直接使用 v-model(或自訂 modelValue)以保持一致性。 |
| 驗證函式過於複雜 | validator 內部執行大量計算會影響渲染效能。 |
只做簡單檢查,複雜驗證放在外部工具或 computed 中處理。 |
最佳實踐
- 盡量使用物件寫法,讓每個 prop 的類型、預設值與驗證都一目了然。
- 保持 Props 的不可變性:子元件只讀取,不直接改寫。
- 為每個 Prop 加上說明文件(或在
props物件中加入 JSDoc 註解),提升團隊可讀性。 - 使用
v-bind="$attrs"讓元件自動接受未在props中宣告的屬性,提升彈性。 - 在大型專案中統一 Prop 命名規則(如全部使用 camelCase),避免因大小寫不一致產生錯誤。
實際應用場景
1. 表單元件的雙向綁定
<!-- FormInput.vue -->
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
<script>
export default {
props: {
modelValue: {
type: String,
default: ''
}
}
}
</script>
父層:
<FormInput v-model="username" />
2. 卡片元件的彈性樣式
// Card.vue
export default {
props: {
title: String,
elevation: {
type: Number,
default: 1,
validator: v => v >= 0 && v <= 5
},
rounded: {
type: Boolean,
default: false
}
}
}
使用:
<Card
title="最新消息"
:elevation="3"
rounded
/>
3. 列表渲染的資料來源
// ItemList.vue
export default {
props: {
items: {
type: Array,
required: true,
validator: arr => arr.every(i => typeof i.id !== 'undefined')
}
}
}
父層:
<ItemList :items="todoList" />
此方式確保傳入的 items 陣列每個元素都有 id,避免在 v-for 中出現 key 錯誤。
總結
- Props 是 Vue3 Options API 中父子元件溝通的核心機制,必須遵守 單向資料流 原則。
- 透過 物件寫法 可以同時設定 類型、預設值、必填與自訂驗證,提升元件的魯棒性。
- 不要在子元件內直接修改 Prop,應使用
$emit(或v-model)讓父層負責更新。 - 正確處理 預設值的引用、validator 的效能、以及
.syncvsv-model的差異,能避免常見的開發陷阱。 - 在實務上,Props 常被用於 表單雙向綁定、彈性樣式設定、以及 資料列表傳遞,只要掌握上述概念,就能寫出可重用、易維護的 Vue3 元件。
希望這篇指南能幫助你在 Vue3 Options API 中更自信地使用 Props,打造高品質的前端應用!祝開發順利 🚀