Skip to content

fix(runtime-core): fix warning for missing event handler #8268

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
22 changes: 19 additions & 3 deletions packages/runtime-core/__tests__/componentEmits.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ describe('component: emit', () => {
})
render(h(Foo), nodeOps.createElement('div'))
expect(
`Component emitted event "bar" but it is neither declared`
`Component emitted event "bar" but didn't declare a "onBar" prop or a "bar" emit option.`
).toHaveBeenWarned()
})

Expand All @@ -178,7 +178,7 @@ describe('component: emit', () => {
})
render(h(Foo), nodeOps.createElement('div'))
expect(
`Component emitted event "bar" but it is neither declared`
`Component emitted event "bar" but didn't declare a "onBar" prop or a "bar" emit option.`
).toHaveBeenWarned()
})

Expand All @@ -194,7 +194,23 @@ describe('component: emit', () => {
})
render(h(Foo), nodeOps.createElement('div'))
expect(
`Component emitted event "foo" but it is neither declared`
`Component emitted event "foo" but didn't declare a "onFoo" prop or a "foo" emit option.`
).not.toHaveBeenWarned()
})

test('should not warn if has equivalent onXXX prop with kebap-cased event', () => {
const Foo = defineComponent({
props: ['onFooBar'],
emits: [],
render() {},
created() {
// @ts-expect-error `$emit` argument type is inferred from empty component `emits` and thus is `never` here
this.$emit('foo-bar')
}
})
render(h(Foo), nodeOps.createElement('div'))
expect(
`Component emitted event "foo-bar" but didn't declare a "onFooBar" prop or a "foo-bar" emit option.`
).not.toHaveBeenWarned()
})

Expand Down
13 changes: 10 additions & 3 deletions packages/runtime-core/src/componentEmits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,17 @@ export function emit(
event.startsWith(compatModelEventPrefix))
)
) {
if (!propsOptions || !(toHandlerKey(event) in propsOptions)) {
if (
!propsOptions ||
!(
// only checking on camelized handler keys since that is what developers should use
// https://github.com/vuejs/vue-next/pull/4804#discussion_r736462241
toHandlerKey(camelize(event)) in propsOptions
)
) {
warn(
`Component emitted event "${event}" but it is neither declared in ` +
`the emits option nor as an "${toHandlerKey(event)}" prop.`
`Component emitted event "${event}" but didn't declare a "${toHandlerKey(camelize(event))}" prop ` +
`or a "${camelize(event)}" emit option.`
Comment on lines +104 to +105
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that this wording came from #4804 (comment), but I think the previous wording (with just the addition of camelize to the prop name) was better. In particular:

  1. The suggestion to use a prop should come last, as using emits is a much more common solution than using a prop.
  2. The suggested name for the emits option in this warning is currently incorrect. e.g. See Playground, which claims that updateFoo should be added to emits, even though it is already included. The check for event in emitsOptions a few lines up isn't using camelize, so the warning needs to be consistent with that.

)
}
} else {
Expand Down