2024-12-16 在 Vue 中,props 和 emits

2024-12-16 在 Vue 中,props 和 emits

在 Vue 中,props 和 emits

在 Vue 中,**propsemits** 是用來實現父子組件之間的數據傳遞的兩種核心機制,主要用於建立單向數據流和事件驅動的交互。


父子組件的架構與數據傳遞流程

1. 父 -> 子:使用 props

父組件可以通過 props 將數據傳遞給子組件。

  • 機制:父組件定義數據,子組件通過 props 接收。
  • 特性:數據是 單向的(從父到子,子不能直接修改 props)。

例子:

父組件:SplitBill.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<AddExpenseModal :members="members" />
</template>

<script>
import AddExpenseModal from './AddExpenseModal.vue';

export default {
components: { AddExpenseModal },
data() {
return {
members: [
{ name: 'Alice', balance: 0 },
{ name: 'Bob', balance: 0 },
],
};
},
};
</script>

子組件:AddExpenseModal.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
<div>
<select v-model="selectedMember">
<option v-for="member in members" :key="member.name" :value="member.name">
{{ member.name }}
</option>
</select>
</div>
</template>

<script>
export default {
props: {
members: {
type: Array,
required: true,
},
},
data() {
return {
selectedMember: '',
};
},
};
</script>

2. 子 -> 父:使用 emits

子組件可以通過 emits 將事件傳遞給父組件,父組件可以監聽這些事件來接收數據或觸發響應。

  • 機制:子組件使用 $emit 發送事件,父組件使用 v-on@ 監聽事件。
  • 特性:事件是 單向的(從子到父,子不能直接改變父組件的狀態)。

例子:

子組件:AddExpenseModal.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<button @click="emitExpense">新增支出</button>
</template>

<script>
export default {
emits: ['add-expense'], // 聲明事件名稱
methods: {
emitExpense() {
const expense = { name: 'Dinner', amount: 100 };
this.$emit('add-expense', expense); // 發送事件給父組件
},
},
};
</script>

父組件:SplitBill.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<AddExpenseModal @add-expense="handleExpense" />
</template>

<script>
import AddExpenseModal from './AddExpenseModal.vue';

export default {
components: { AddExpenseModal },
methods: {
handleExpense(expense) {
console.log('收到的支出:', expense); // 在此處接收子組件傳來的數據
},
},
};
</script>

propsemits 的關係與設計哲學

  1. 單向數據流

    • Vue 遵循「數據由上而下,事件由下而上」的設計。
    • 父組件用 props 給子組件提供數據。
    • 子組件用 emits 通知父組件狀態變化。
  2. 分工明確

    • props 用於傳遞靜態或基於父組件動態變化的數據。
    • emits 用於傳遞交互事件或通知父組件數據更新。
  3. 解耦性高

    • 子組件不需要直接操作父組件的數據,只需要 emit 事件,保持子組件的獨立性和可重用性。

完整架構:父子數據交互示意圖

1
2
3
4
5
6
7
8
父組件 SplitBill.vue
↓ (數據傳遞)
props:members

子組件 AddExpenseModal.vue

emits:add-expense
↑ (事件回傳)

3. 在設計父子交互時的注意事項

  • 命名一致性
    子組件的 propsemits 名稱要清晰、語義化,方便父組件理解。

  • 避免過多的父子耦合
    如果父子組件的數據傳遞過於頻繁,可以考慮用 Vuex 或其他狀態管理工具。

  • **不能直接修改 props**:
    子組件如需修改數據,應通過 $emit 通知父組件更新,不能直接更改 props