Known events aren't removed from $attrs
Version
3.0.2
Reproduction link
https://jsfiddle.net/pqte0h2s/
Steps to reproduce
Just like declared $props
are removed from $attrs
and are never inherited,
declared $emits
should also be removed from $attrs
.
It looks like they aren't and this can cause unexpected behaviors.
In the linked repro, try to type in the input box. The outer y
variable shouldn't change.
What is expected?
y
shouldn't change, because the C1
component doesn't raise update:modelValue
event.
onUpdateModelValue
can be found in $attrs
, which I wouldn't expect.
What is actually happening?
y
is updated, because the app @update:modelValue
event was put into $attrs
, which the C1
component passes down to input
.
Only unknown events (that are not declared in emits
) should be found in $attrs
.
BTW, if you pass null or undefined to an event handler, Vue still binds it and crashes when trying to call it. So the following isn't a convenient way to work-around this issue:
<input v-bind="{ ...$attrs, "onUpdate:modelValue": undefined }">
In some places, such as functional components, it is convenient to be able to pass an optional event handler without resorting to if statements. I leave it to your judgement if that's something you think is worth supporting.
@skirtles-code Thank you and that seems to fix the repro! I'll check tomorrow in my real app if that was the issue after all.
Although if that is, I'm surprised everything was ok with TS and there was nothing on the console in dev mode. Are you not supposed to get some kind of warnings if you raise undeclared events?
Follow-up on that issue from my real project:
It was indeed just a typo in emits
that I did not notice.
TS was not kicking in because if you don't declare any emits
at all, then emit()
is typed to accept any string, so it worked. I believe there is no runtime warning for the same reason.
eslint-vue-plugin has a rule for that and it should have warned me. And that's actually an SFC tooling bug where some warnings seem to be lost in incremental rebuilds. I opened vuejs/vue-loader#1760 to track this.