元件事件
本頁面假設您已經閱讀了元件基礎知識。如果您是元件的新手,請先閱讀。
發出和監聽事件
元件可以直接在模板表示式(例如,在v-on
處理器中)中使用內建的$emit
方法發出自定義事件
模板
<!-- MyComponent -->
<button @click="$emit('someEvent')">Click Me</button>
父元件可以使用v-on
監聽它
模板
<MyComponent @some-event="callback" />
元件事件監聽器也支援.once
修飾符
模板
<MyComponent @some-event.once="callback" />
與元件和props一樣,事件名稱提供自動的大小寫轉換。注意我們發出的是camelCase事件,但可以在父元件中使用kebab-cased監聽器來監聽它。與props的大小寫一樣,我們建議在模板中使用kebab-cased事件監聽器。
提示
與原生DOM事件不同,元件發出的事件不會冒泡。您只能監聽直接子元件發出的事件。如果需要在不同兄弟元件或深層巢狀元件之間進行通訊,請使用外部事件匯流排或全域性狀態管理解決方案。
事件引數
有時,在事件中發出特定值很有用。例如,我們可能希望<BlogPost>
元件負責調整文字的大小。在這些情況下,我們可以向$emit
傳遞額外的引數以提供此值
模板
<button @click="$emit('increaseBy', 1)">
Increase by 1
</button>
然後,當我們監聽父元件中的事件時,我們可以使用內聯箭頭函式作為監聽器,這允許我們訪問事件引數
模板
<MyButton @increase-by="(n) => count += n" />
或者,如果事件處理器是一個方法
模板
<MyButton @increase-by="increaseCount" />
那麼值將作為該方法的第一個引數傳遞
js
function increaseCount(n) {
count.value += n
}
提示
所有傳遞給$emit()
的額外引數(在事件名稱之後)都將轉發給監聽器。例如,使用$emit('foo', 1, 2, 3)
時,監聽函式將接收到三個引數。
宣告事件
元件可以使用defineEmits()
宏(defineEmits()
)顯式宣告它將發出的事件 。
vue
<script setup>
defineEmits(['inFocus', 'submit'])
</script>
我們在<template>
中使用的$emit
方法在元件的<script setup>
部分中不可用,但defineEmits()
返回一個等效函式,我們可以用它來代替。
vue
<script setup>
const emit = defineEmits(['inFocus', 'submit'])
function buttonClick() {
emit('submit')
}
</script>
defineEmits()
宏不能在函式中使用,它必須直接放在上面的示例中<script setup>
內。
如果你使用的是顯式的setup
函式而不是<script setup>
,則應使用emits
選項來宣告事件,並且emit
函式將在setup()
上下文中暴露。
js
export default {
emits: ['inFocus', 'submit'],
setup(props, ctx) {
ctx.emit('submit')
}
}
與setup()
上下文的其他屬性一樣,emit
可以安全地進行解構。
js
export default {
emits: ['inFocus', 'submit'],
setup(props, { emit }) {
emit('submit')
}
}
emits
選項和defineEmits()
宏也支援物件語法。如果你使用TypeScript,你可以對引數進行型別註解,這使得我們可以在執行時驗證發出事件的負載。
vue
<script setup lang="ts">
const emit = defineEmits({
submit(payload: { email: string, password: string }) {
// return `true` or `false` to indicate
// validation pass / fail
}
})
</script>
如果你使用TypeScript與<script setup>
一起使用,也可以使用純型別註解來聲明發出的事件。
vue
<script setup lang="ts">
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
</script>
更多資訊:元件發出事件的型別註解
雖然這不是必需的,但建議定義所有發出的事件,以便更好地記錄元件應該如何工作。這也允許Vue排除已知的監聽器從穿透屬性,避免由第三方程式碼手動派發的DOM事件引起的邊緣情況。
提示
如果將原生事件(例如,click
)定義在emits
選項中,監聽器現在將僅監聽元件發出的click
事件,而不再響應原生click
事件。
事件驗證
與屬性型別驗證類似,如果使用物件語法而不是陣列語法定義,則可以驗證發出的事件。
要新增驗證,將事件分配給一個函式,該函式接收傳遞給emit
呼叫的引數,並返回一個布林值以指示事件是否有效。
vue
<script setup>
const emit = defineEmits({
// No validation
click: null,
// Validate submit event
submit: ({ email, password }) => {
if (email && password) {
return true
} else {
console.warn('Invalid submit event payload!')
return false
}
}
})
function submitForm(email, password) {
emit('submit', { email, password })
}
</script>