Skip to content

Commit c1cd42e

Browse files
committed
fix(runtime-core): fix v-on object kebab-case event emit matching
fix #3527
1 parent 995d76b commit c1cd42e

File tree

2 files changed

+60
-8
lines changed

2 files changed

+60
-8
lines changed

packages/runtime-core/__tests__/componentEmits.spec.ts

+54-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
// Note: emits and listener fallthrough is tested in
22
// ./rendererAttrsFallthrough.spec.ts.
33

4-
import { render, defineComponent, h, nodeOps } from '@vue/runtime-test'
4+
import {
5+
render,
6+
defineComponent,
7+
h,
8+
nodeOps,
9+
toHandlers
10+
} from '@vue/runtime-test'
511
import { isEmitListener } from '../src/componentEmits'
612

713
describe('component: emit', () => {
@@ -28,7 +34,7 @@ describe('component: emit', () => {
2834
expect(onBaz).toHaveBeenCalled()
2935
})
3036

31-
test('trigger camelize event', () => {
37+
test('trigger camelCase handler', () => {
3238
const Foo = defineComponent({
3339
render() {},
3440
created() {
@@ -43,7 +49,52 @@ describe('component: emit', () => {
4349
})
4450
render(h(Comp), nodeOps.createElement('div'))
4551

46-
expect(fooSpy).toHaveBeenCalled()
52+
expect(fooSpy).toHaveBeenCalledTimes(1)
53+
})
54+
55+
test('trigger kebab-case handler', () => {
56+
const Foo = defineComponent({
57+
render() {},
58+
created() {
59+
this.$emit('test-event')
60+
}
61+
})
62+
63+
const fooSpy = jest.fn()
64+
const Comp = () =>
65+
h(Foo, {
66+
'onTest-event': fooSpy
67+
})
68+
render(h(Comp), nodeOps.createElement('div'))
69+
70+
expect(fooSpy).toHaveBeenCalledTimes(1)
71+
})
72+
73+
// #3527
74+
test('trigger mixed case handlers', () => {
75+
const Foo = defineComponent({
76+
render() {},
77+
created() {
78+
this.$emit('test-event')
79+
this.$emit('testEvent')
80+
}
81+
})
82+
83+
const fooSpy = jest.fn()
84+
const barSpy = jest.fn()
85+
const Comp = () =>
86+
// simulate v-on="obj" usage
87+
h(
88+
Foo,
89+
toHandlers({
90+
'test-event': fooSpy,
91+
testEvent: barSpy
92+
})
93+
)
94+
render(h(Comp), nodeOps.createElement('div'))
95+
96+
expect(fooSpy).toHaveBeenCalledTimes(1)
97+
expect(fooSpy).toHaveBeenCalledTimes(1)
4798
})
4899

49100
// for v-model:foo-bar usage in DOM templates

packages/runtime-core/src/componentEmits.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -114,14 +114,15 @@ export function emit(
114114
}
115115
}
116116

117-
// convert handler name to camelCase. See issue #2249
118-
let handlerName = toHandlerKey(camelize(event))
119-
let handler = props[handlerName]
117+
let handlerName
118+
let handler =
119+
props[(handlerName = toHandlerKey(event))] ||
120+
// also try camelCase event handler (#2249)
121+
props[(handlerName = toHandlerKey(camelize(event)))]
120122
// for v-model update:xxx events, also trigger kebab-case equivalent
121123
// for props passed via kebab-case
122124
if (!handler && isModelListener) {
123-
handlerName = toHandlerKey(hyphenate(event))
124-
handler = props[handlerName]
125+
handler = props[(handlerName = toHandlerKey(hyphenate(event)))]
125126
}
126127

127128
if (handler) {

0 commit comments

Comments
 (0)