Subscribe on changes!

Inline handlers for v-on causing unnecessary child updates

avatar
Sep 8th 2020

Version

3.0.0-rc.10

Reproduction link

https://jsfiddle.net/skirtle/9f1nvw2s/

Steps to reproduce

  1. Open the console.
  2. Click the top button, Click me.
  3. 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.

avatar
Sep 10th 2020

make sense.