Vue3 事件名稱大小寫轉換機制
子元件這樣送出事件:
this.$emit('changeSource')
父元件卻這樣接:
<MyComponent @change-source="onChangeSource" />
然後,竟然可以正常運作。
這篇文章會完整拆解 Vue 3 的事件名稱大小寫轉換機制,並對照 Vue 2 的差異,最後給出團隊可落地的命名與 lint 建議。
先講結論
- 在 Vue 3,
emit('changeSource')與@change-source可以互相對應,這是官方支援行為。[1] - 在 Vue 2,官方文件明確說明自訂事件名稱不會自動做大小寫轉換;若命名不一致會監聽不到。[2]
- 即使在 Vue 3,官方仍建議在 template 裡使用 kebab-case 事件名稱,以維持一致性與可讀性。[1]
Vue 2 與 Vue 3 差在哪裡?
Vue 2:名稱必須精準匹配
Vue 2 文件指出,自訂事件名稱不會像 component / prop 一樣做自動大小寫轉換;如果你 emit myEvent,監聽 my-event 通常不會生效。[2]
此外,Vue 2 文件也提到:在 DOM template 情境下,HTML attribute 名稱不分大小寫,可能導致大小寫事件名更容易踩雷,因此建議使用 kebab-case。[2]
Vue 3:camelCase 與 kebab-case 可對應
Vue 3 官方文件在 Component Events 明確示範:子元件 emit camelCase 事件時,父元件可用 kebab-case 監聽,且官方建議 template 使用 kebab-case 保持一致。[1]
這個設計把事件命名行為往 props 的使用體驗靠攏,減少因大小寫不一致造成的溝通與維護成本。
實作範例(Vue 3)
子元件
<script setup>
const emit = defineEmits(['changeSource'])
function updateSource() {
emit('changeSource', { from: 'A', to: 'B' })
}
</script>
<template>
<button @click="updateSource">Change</button>
</template>
父元件
<template>
<ChildComponent @change-source="handleChangeSource" />
</template>
<script setup>
function handleChangeSource(payload) {
console.log(payload)
}
</script>
以上在 Vue 3 是可行且常見的寫法。[1]
什麼時候還是會出問題?
- 專案混用 Vue 2 與 Vue 3 語法認知,導致錯誤套用規則。
- 事件名稱拼字不同(不是大小寫問題,而是字串不同),例如
change-sourcevssource-change。 - 沒有宣告
emits(或defineEmits)時,團隊很難從型別與 lint 提前發現錯字。
團隊最佳實踐
Template 一律用 kebab-case:
@change-source。事件宣告集中管理:使用
emits或defineEmits,降低拼字錯誤。加上 lint 約束:
vue/v-on-event-hyphenation:規範 template 事件監聽名稱格式。[4]vue/custom-event-name-casing:規範自訂事件名稱風格。[5]
- 文件化命名策略:在專案 README 或 Contributing Guide 寫清楚「JS 端 emit 與 template 端 listener 的命名約定」。
延伸:emits 在 Vue 3 的價值
Vue 3 migration guide 指出,Vue 3 引入 emits 選項,讓元件能明確宣告可以送出的事件。[3]
這不只是語法糖,而是可維護性升級:
- 元件對外事件介面更清楚。
- 搭配型別與工具鏈更容易發現不合法事件。
- 在大型團隊合作時,可降低「事件名稱靠默契」造成的錯誤。
一份可直接採用的命名規範
- 事件語意使用動詞或動詞片語:
submitted、change-source、dialog-opened。 - JS 內部若使用 camelCase emit(例如
emit('changeSource')),template 仍統一監聽 kebab-case(@change-source)。[1] - 不使用縮寫與模糊詞(如
chgSrc),避免跨人員理解成本。
總結
你看到 this.$emit('changeSource') 能被 @change-source 接住,在 Vue 3 是預期行為,不是框架 bug。核心差異在於:
- Vue 2 對事件名稱大小寫更嚴格,需精準匹配。[2]
- Vue 3 支援 camelCase / kebab-case 對應,提升開發體驗。[1]
- 實務上仍建議 template 使用 kebab-case,並搭配 lint +
emits做一致化治理。[3][4][5]
參考資料
Vue.js Official Docs, Component Events
https://vuejs.org/guide/components/events
存取日期:2026-04-12Vue 2 Official Docs, Custom Events (Event Names)
https://v2.vuejs.org/v2/guide/components-custom-events.html
存取日期:2026-04-12Vue 3 Migration Guide, emits Option
https://v3-migration.vuejs.org/breaking-changes/emits-option.html
存取日期:2026-04-12eslint-plugin-vue, vue/v-on-event-hyphenation
https://eslint.vuejs.org/rules/v-on-event-hyphenation
存取日期:2026-04-12eslint-plugin-vue, vue/custom-event-name-casing
https://eslint.vuejs.org/rules/custom-event-name-casing.html
存取日期:2026-04-12GitHub Issue, camelCase events can be listened to in the kebab-case (#656)
https://github.com/vuejs/docs/issues/656
存取日期:2026-04-12
留言
張貼留言