Inline handlers for v-on causing unnecessary child updates
Version
3.0.0-rc.10
Reproduction link
https://jsfiddle.net/skirtle/9f1nvw2s/
Steps to reproduce
- Open the console.
- Click the top button,
Click me
. - Observe the logging.
What is expected?
In Vue 2 the parent component would have re-rendered but the child components would not.
See https://jsfiddle.net/skirtle/rxgv78mt/1/ for a Vue 2 example.
I believe it would be preferable for the Vue 2 behaviour to be retained in Vue 3.
What is actually happening?
The child components are all re-rendered.
This is a toy example but it shows a common usage pattern for events with v-for
.
The child updates are triggered by the presence of the attribute @chosen="onChosen(item)"
. A listener like this is pretty typical for a v-for
. Because this is an inline expression it will be wrapped in a function. A new function will be created every time the parent renders, so this 'prop' has changed from a ===
perspective.
I have included both emits
and inheritAttrs: false
in the child to ensure that this listener is not used during rendering.
As I understand it, the check in shouldUpdateComponent
compares VNode 'props' and will trigger a re-render if any have changed. The new wrapper function for the listener counts as a change from that perspective, even though it isn't used during child rendering.
The underlying cause is essentially the same as #1181. That issue was closed because nobody was able to provide a realistic use-case.
I was unaware of that issue when I reported #1790. Despite providing several use-cases that was closed as a duplicate of #1181.
Neither of those issues explicitly mentioned events. As the use-case provided here is different, with the potential for a different solution, I thought it was worth reporting again.