]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): fix v-on object kebab-case event emit matching
authorEvan You <yyx990803@gmail.com>
Thu, 1 Apr 2021 23:47:58 +0000 (19:47 -0400)
committerEvan You <yyx990803@gmail.com>
Thu, 1 Apr 2021 23:47:58 +0000 (19:47 -0400)
fix #3527

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

index a02cbb880c13e90817e6fa67faad3de0e7105e76..0fac2d85531201639040faac3c37ce16e2dd3792 100644 (file)
@@ -1,7 +1,13 @@
 // Note: emits and listener fallthrough is tested in
 // ./rendererAttrsFallthrough.spec.ts.
 
-import { render, defineComponent, h, nodeOps } from '@vue/runtime-test'
+import {
+  render,
+  defineComponent,
+  h,
+  nodeOps,
+  toHandlers
+} from '@vue/runtime-test'
 import { isEmitListener } from '../src/componentEmits'
 
 describe('component: emit', () => {
@@ -28,7 +34,7 @@ describe('component: emit', () => {
     expect(onBaz).toHaveBeenCalled()
   })
 
-  test('trigger camelize event', () => {
+  test('trigger camelCase handler', () => {
     const Foo = defineComponent({
       render() {},
       created() {
@@ -43,7 +49,52 @@ describe('component: emit', () => {
       })
     render(h(Comp), nodeOps.createElement('div'))
 
-    expect(fooSpy).toHaveBeenCalled()
+    expect(fooSpy).toHaveBeenCalledTimes(1)
+  })
+
+  test('trigger kebab-case handler', () => {
+    const Foo = defineComponent({
+      render() {},
+      created() {
+        this.$emit('test-event')
+      }
+    })
+
+    const fooSpy = jest.fn()
+    const Comp = () =>
+      h(Foo, {
+        'onTest-event': fooSpy
+      })
+    render(h(Comp), nodeOps.createElement('div'))
+
+    expect(fooSpy).toHaveBeenCalledTimes(1)
+  })
+
+  // #3527
+  test('trigger mixed case handlers', () => {
+    const Foo = defineComponent({
+      render() {},
+      created() {
+        this.$emit('test-event')
+        this.$emit('testEvent')
+      }
+    })
+
+    const fooSpy = jest.fn()
+    const barSpy = jest.fn()
+    const Comp = () =>
+      // simulate v-on="obj" usage
+      h(
+        Foo,
+        toHandlers({
+          'test-event': fooSpy,
+          testEvent: barSpy
+        })
+      )
+    render(h(Comp), nodeOps.createElement('div'))
+
+    expect(fooSpy).toHaveBeenCalledTimes(1)
+    expect(fooSpy).toHaveBeenCalledTimes(1)
   })
 
   // for v-model:foo-bar usage in DOM templates
index 6d6ca4aaed87afe5e598bbbca8c001a860ec9063..ab382edc80c53c3971b6e509e79cca890b119c17 100644 (file)
@@ -114,14 +114,15 @@ export function emit(
     }
   }
 
-  // convert handler name to camelCase. See issue #2249
-  let handlerName = toHandlerKey(camelize(event))
-  let handler = props[handlerName]
+  let handlerName
+  let handler =
+    props[(handlerName = toHandlerKey(event))] ||
+    // also try camelCase event handler (#2249)
+    props[(handlerName = toHandlerKey(camelize(event)))]
   // for v-model update:xxx events, also trigger kebab-case equivalent
   // for props passed via kebab-case
   if (!handler && isModelListener) {
-    handlerName = toHandlerKey(hyphenate(event))
-    handler = props[handlerName]
+    handler = props[(handlerName = toHandlerKey(hyphenate(event)))]
   }
 
   if (handler) {