組件可以通過$emit(functionName, params)
自定義事件名稱並傳遞參數。自定義事件名稱建議使用kebab-case
來命名自定義事件名稱,以確保命名風格
與HTML 屬性
一致性。此外,自定義事件還支持事件修飾符
(例如:.once)。需要特別注意的是,自定義事件是將子組件的值傳遞給父組件,並不會觸發事件冒泡機制
。
Vue 組件中的數據傳遞除了常見的父子傳值之外,還有兩種其他的方式可以使用:
provide
和inject
API,實現祖孫或更深層次組件間的數據傳遞。這種方式避免了逐層傳遞 props
的麻煩,適合跨層級的組件通信。狀態管理工具
,如Pinia
或Vuex
。這些工具可以集中管理應用的全局狀態,實現組件間數據同步。以下透過子組件按鈕傳遞訊息給父組件參數並顯示出來舉例基本用法:
👉 Vue3 Options API emit 基本用法實作連結
父組件 Vue Template:
<div id="app">
<child-component @send-msg="getMessage"></child-component>
</div>
⭐ 如果容易搞混也可以間單記「前內後外」的方式,前面是子組件定義事件名稱,後面是父組件接收子組件傳遞參數的處理函數名稱。
父組件 javascript:
const rootComponent = {
methods: {
getMessage(params) {
alert(`收到訊息:${params}`);
}
},
components: { childComponent }
};
子組件 Vue Template:
<template id="child">
<button type="button" @click="sendMessage">子組件傳送訊息</button>
</template>
子組件 javascript:
const childComponent = {
template: "#child",
methods: {
sendMessage() {
// 自定義事件名稱:sendMsg、參數值:"hello Vue"
this.$emit("sendMsg", "hello Vue");
}
}
};
⭐ 在為元素綁定事件時,通常會使用標準事件名稱(例如:click)。而當為組件綁定自定義事件
時,操作原理與元素綁定事件相似,不同之處在於我們綁定的是子組件通過$emit
發送的自定義事件名稱(例如:send-msg
)。
在Day18中提到,子組件可以對父組件傳入的props
進行驗證,同樣地,子組件在發送自定義事件
之前,也可以對事件所回傳的數據進行檢查。通過返回布林值(Boolean)
,可以判斷回傳的數據是否符合預期,從而確保發送的是合法數據。
這邊我們將上面案例中的子組件做emit
的聲明驗證:
👉 Vue3 Options API emit 參數定義驗證方法實作連結
子組件 javaScript:
const childComponent = {
emits: {
// params 是 emit 發送出去的值
sendMsg: (params) => params !== undefined
},
template: "#child",
methods: {
sendMessage() {
// 自定義事件名稱:sendMsg、參數值:"hello Vue"
this.$emit("sendMsg", "hello Vue");
}
}
};
為了實驗的目的,我們可以將"hello Vue"
替換為undefined
,故意使其驗證失敗,從而觀察控制台中的警告訊息。
在驗證過程中,如果同時傳遞多個參數,需要對應的欄位數量來接收,否則容易導致錯誤,並且後續調整也相對難以維護。為了提高可讀性與可維護性,建議使用物件的方式傳遞參數,並在函數中通過解構來取得物件的屬性值。
👉 Vue3 Options API emit 多參數定義驗證(使用對應數量的參數)實作連結
這邊我們將上面案例中的子組件做從原本只傳遞一個參數變成傳遞三個參數:
子組件 javascript:
const childComponent = {
emits: {
// ...args 可以接收到所有傳遞的參數
sendMsg: (vueMsg, reactMsg, angularMsg) => vueMsg && reactMsg && angularMsg
},
template: "#child",
methods: {
sendMessage() {
// 自定義事件名稱:sendMsg、參數值:"hello Vue", "hello React", "hello Angular"
this.$emit("sendMsg", "hello Vue", "hello React", "hello Angular");
}
}
};
父組件 Vue Template:
<div id="app">
<child-component @send-msg="getMessage"></child-component>
</div>
父組件 javascript:
const rootComponent = {
methods: {
// ...params可以讀取到多個子組件傳遞的參數
getMessage(vueMsg, reactMsg, angularMsg) {
alert(`收到訊息:vueMsg:${vueMsg},reactMsg:${reactMsg},angularMsg:${angularMsg}`);
}
},
components: { childComponent }
};
使用物件
包裝傳送值並搭配解構
的方式取得物件內部屬性寫法:
👉 Vue3 Options API emit 多參數定義驗證(使用物件)實作連結
子組件 javascript:
sendMessage() {
// 自定義事件名稱:sendMsg、參數值:msgInfo 物件
const msgInfo = {
vueMsg: "hello Vue",
reactMsg: "hello React",
angularMsg: "hello Angular"
};
this.$emit("sendMsg", msgInfo);
}
...略
父組件 javascript:
getMessage({ vueMsg, reactMsg, angularMsg } = {}) {
alert(
`收到訊息:vueMsg:${vueMsg},reactMsg:${reactMsg},angularMsg:${angularMsg}`
);
}
}
...略
當emits
驗證未通過時,Vue
會顯示警告訊息,但並不會阻止程式的正常運行。更重要的是,透過這種聲明式的方式,不僅能對事件參數進行驗證,還能在編寫程式碼的同時,自然地起到部分文件化的作用,從而提升程式碼的可維護性。
props
向子組件傳遞數據,當子組件需要回傳變動的數據時,可以使用$emit
發送自訂事件,實現與父組件的雙向互動。emits
事件時,應對回傳數據進行驗證,並返回布林值來判斷數據是否符合預期。在開發環境中,若emits
發送的數據不符合驗證條件,將顯示警告訊息,但不會影響程式的正常運行。