]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): use consistent camelCase event casing for render functions (#2278)
authorshadowings-zy <shadowingszy@outlook.com>
Tue, 6 Oct 2020 22:28:56 +0000 (06:28 +0800)
committerGitHub <noreply@github.com>
Tue, 6 Oct 2020 22:28:56 +0000 (18:28 -0400)
close #2249

packages/compiler-core/src/transforms/vOn.ts
packages/runtime-core/__tests__/componentEmits.spec.ts
packages/runtime-core/src/componentEmits.ts

index 9bd5b2a46e0223bab8c6e96ac2e79b9a3b807d12..31dd16a0bde2408f52e9d1ad7f2fed7e2b135d6a 100644 (file)
@@ -42,10 +42,8 @@ export const transformOn: DirectiveTransform = (
   if (arg.type === NodeTypes.SIMPLE_EXPRESSION) {
     if (arg.isStatic) {
       const rawName = arg.content
-      // for @vnode-xxx event listeners, auto convert it to camelCase
-      const normalizedName = rawName.startsWith(`vnode`)
-        ? capitalize(camelize(rawName))
-        : capitalize(rawName)
+      // for all event listeners, auto convert it to camelCase. See issue #2249
+      const normalizedName = capitalize(camelize(rawName))
       eventName = createSimpleExpression(`on${normalizedName}`, true, arg.loc)
     } else {
       eventName = createCompoundExpression([
index 973099545e0ad87ad93370f921c61d63c0c1a830..317b36f8ccbdee99572038b39a2c1bc20bc074b5 100644 (file)
@@ -28,6 +28,24 @@ describe('component: emit', () => {
     expect(onBaz).toHaveBeenCalled()
   })
 
+  test('trigger camelize event', () => {
+    const Foo = defineComponent({
+      render() {},
+      created() {
+        this.$emit('test-event')
+      }
+    })
+
+    const fooSpy = jest.fn()
+    const Comp = () =>
+      h(Foo, {
+        onTestEvent: fooSpy
+      })
+    render(h(Comp), nodeOps.createElement('div'))
+
+    expect(fooSpy).toHaveBeenCalled()
+  })
+
   // for v-model:foo-bar usage in DOM templates
   test('trigger hyphenated events for update:xxx events', () => {
     const Foo = defineComponent({
index ac37bc568d8aa8f147a13f5e672abb69d64396ad..d8578589c4e240326033d549810b94435224af40 100644 (file)
@@ -6,12 +6,14 @@ import {
   capitalize,
   hyphenate,
   isFunction,
-  extend
+  extend,
+  camelize
 } from '@vue/shared'
 import {
   ComponentInternalInstance,
   ComponentOptions,
-  ConcreteComponent
+  ConcreteComponent,
+  formatComponentName
 } from './component'
 import { callWithAsyncErrorHandling, ErrorCodes } from './errorHandling'
 import { warn } from './warning'
@@ -78,7 +80,24 @@ export function emit(
     devtoolsComponentEmit(instance, event, args)
   }
 
-  let handlerName = `on${capitalize(event)}`
+  if (__DEV__) {
+    const lowerCaseEvent = event.toLowerCase()
+    if (lowerCaseEvent !== event && props[`on` + capitalize(lowerCaseEvent)]) {
+      warn(
+        `Event "${lowerCaseEvent}" is emitted in component ` +
+          `${formatComponentName(
+            instance,
+            instance.type
+          )} but the handler is registered for "${event}". ` +
+          `Note that HTML attributes are case-insensitive and you cannot use ` +
+          `v-on to listen to camelCase events when using in-DOM templates. ` +
+          `You should probably use "${hyphenate(event)}" instead of "${event}".`
+      )
+    }
+  }
+
+  // convert handler name to camelCase. See issue #2249
+  let handlerName = `on${capitalize(camelize(event))}`
   let handler = props[handlerName]
   // for v-model update:xxx events, also trigger kebab-case equivalent
   // for props passed via kebab-case