組件通信:自定義事件
在 Vue 3 中,組件之間的通信可以通過自定義事件來實現,這是讓子組件與父組件交互的核心方式之一。自定義事件允許子組件向父組件發送通知,並觸發父組件的相應邏輯,這種模式在父組件傳遞數據給子組件後,需要子組件進行回饋的場景中非常有用。
1. 什麼是自定義事件?
自定義事件是 Vue 中的一種通信機制,子組件可以使用 $emit()
來觸發事件,父組件可以通過監聽這些事件來響應子組件的行為。
使用場景:
- 當父組件需要知道子組件內發生的某些行為時(如按鈕點擊、表單提交等)。
- 子組件需要向父組件傳遞信息或結果。
- 父組件希望在子組件觸發某些操作後執行相應的邏輯。
2. 如何使用自定義事件?
自定義事件的使用分為兩部分:子組件觸發事件,以及 父組件監聽事件。
1. 子組件觸發事件 ($emit
)
子組件使用 $emit()
方法來觸發自定義事件。這個方法的第一個參數是事件名稱,第二個參數是可選的事件傳遞數據。
範例:
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
<div id="app">
<child-component @custom-event="handleCustomEvent"></child-component>
</div>
<script>
const app = Vue.createApp({
methods: {
handleCustomEvent(payload) {
console.log('Custom event received:', payload);
}
},
components: {
'child-component': {
template: '<button @click="emitEvent">Click Me</button>',
methods: {
emitEvent() {
this.$emit('custom-event', 'Hello from Child!');
}
}
}
}
});
app.mount('#app');
</script>
在這個範例中:
- 子組件:當按鈕被點擊時,子組件透過
$emit('custom-event', 'Hello from Child!')
觸發一個名為custom-event
的事件,並傳遞一個訊息作為參數。 - 父組件:父組件使用
@custom-event="handleCustomEvent"
來監聽這個事件,當事件被觸發時,handleCustomEvent
方法會被執行,並接收到來自子組件的訊息。
2. 父組件監聽事件
父組件可以使用 Vue 的事件綁定語法 @event-name="method"
來監聽子組件觸發的自定義事件。在事件被觸發時,綁定的方法會被調用,並且可以接收子組件傳遞過來的數據。
範例中的 @custom-event="handleCustomEvent"
就是父組件監聽事件的語法。
3. 事件傳遞數據
在 $emit()
觸發事件時,可以傳遞任意數據給父組件。父組件可以在響應的處理方法中接收到這些數據。
範例:
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
26
27
28
29
30
31
32
33
34
35
<div id="app">
<child-component @submit="handleSubmit"></child-component>
</div>
<script>
const app = Vue.createApp({
methods: {
handleSubmit(formData) {
console.log('Form data received:', formData);
}
},
components: {
'child-component': {
template: `
<form @submit.prevent="submitForm">
<input v-model="name" placeholder="Enter your name">
<button type="submit">Submit</button>
</form>
`,
data() {
return {
name: ''
};
},
methods: {
submitForm() {
this.$emit('submit', this.name); // 傳遞數據給父組件
}
}
}
}
});
app.mount('#app');
</script>
在這個範例中,子組件有一個表單,當表單提交時,子組件會透過 $emit('submit', this.name)
將表單數據(使用者的姓名)傳遞給父組件。父組件會監聽 submit
事件,並通過 handleSubmit
方法處理這些數據。
4. 帶參數的事件監聽器
有時父組件可能需要在事件觸發時傳入自己的參數,這時可以使用箭頭函數來處理。
範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div id="app">
<child-component @custom-event="handleCustomEvent('Parent data')"></child-component>
</div>
<script>
const app = Vue.createApp({
methods: {
handleCustomEvent(parentData) {
return (childData) => {
console.log('Parent data:', parentData);
console.log('Child data:', childData);
};
}
},
components: {
'child-component': {
template: '<button @click="$emit(\'custom-event\', \'Child data\')">Click Me</button>'
}
}
});
app.mount('#app');
</script>
在這裡,當子組件觸發 custom-event
時,父組件既可以使用自己的參數,也可以接收子組件傳遞過來的數據。這樣的方式非常適合複雜場景。
5. 事件名的命名規範
在 Vue 中,事件名稱應遵循一個約定:事件名稱使用 kebab-case(短橫線命名)。例如,custom-event
而非 customEvent
。這是因為在 HTML 中,屬性名是不區分大小寫的。
範例:
1
2
3
<div id="app">
<child-component @custom-event="handleCustomEvent"></child-component>
</div>
在 JavaScript 內部,事件名不區分大小寫,但在 HTML 中會轉換為小寫,所以使用 kebab-case
是更一致的寫法。
6. 原生事件 vs 自定義事件
- 原生事件(如
click
、input
)是瀏覽器提供的 HTML 元素的事件,可以直接使用。 - 自定義事件 是 Vue 組件中用來觸發和監聽的事件,這些事件並不依賴於瀏覽器的事件系統,而是 Vue 自己的機制。
如果需要將事件綁定到子組件的根 HTML 元素,而非自定義的 Vue 組件事件,可以使用 .native
修飾符來監聽子組件的原生事件:
1
<child-component @click.native="handleClick"></child-component>
這樣,click
事件會直接綁定到子組件的根元素上,而不是 Vue 自定義的 click
事件。
7. v-model 與自定義事件
Vue 的 v-model
綁定實際上是基於事件通信的。在 Vue 3 中,子組件需要透過 $emit('update:modelValue', value)
來觸發 v-model
的更新。
範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div id="app">
<child-component v-model="parentValue"></child-component>
</div>
<script>
const app = Vue.createApp({
data() {
return {
parentValue: 'Initial Value'
};
},
components: {
'child-component': {
props: ['modelValue'],
template: `<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)">`
}
}
});
app.mount('#app');
</script>
在這個例子中,v-model
在父組件中綁定了 parentValue
,子組件透過 update:modelValue
事件來告訴父組件更新其數據。
總結
- 子組件可以透過
$emit()
來觸發自定義事件,父組件通過@event
語法來監聽這些事件。 - 子組件可以向父組件傳遞事件參數,父組件可以根據參數執行相應邏輯。
- 自定義事件是 Vue 中常見的組件通信方式,特別是父子組件之間的數據回饋。
- Vue 3 還提供了進階的通信方式,例如
v-model
綁定以及帶參數的事件監聽。
這些特性讓 Vue 的自定義事件系統變得靈活且高效,使得組件間的交互更加流暢。