Skip to content
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

`beforeUpdate` is not called if we explicitly state `v-slot:default` #10986

Closed
WofWca opened this issue Jan 6, 2020 · 7 comments
Closed

`beforeUpdate` is not called if we explicitly state `v-slot:default` #10986

WofWca opened this issue Jan 6, 2020 · 7 comments

Comments

@WofWca
Copy link

@WofWca WofWca commented Jan 6, 2020

Version

2.6.11

Reproduction link

https://jsfiddle.net/WofWca/da0v8nqc/23/

Steps to reproduce

Click on the gray box under "With `v-slot:default`:"

What is expected?

beforeUpdate of WithVSlot component is called.

What is actually happening?

It is NOT called.


Under "No `v-slot`:" there is an identical component, except it lacks v-slot:default. It works as I expect it.

@WofWca WofWca changed the title `beforeUpdate` is not called if we add `v-slot="props"` `beforeUpdate` is not called if we explicitly state `v-slot:default` Jan 6, 2020
@despreston

This comment has been minimized.

Copy link

@despreston despreston commented Jan 13, 2020

I can confirm this is broken for all named slots, regardless of the name.

@despreston

This comment has been minimized.

Copy link

@despreston despreston commented Jan 13, 2020

maybe some more useful info:

While testing the failing component in the original example, on this line, https://github.com/vuejs/vue/blob/dev/src/core/instance/lifecycle.js#L200, vm does not contain a vm.$options.beforeUpdate in the prototype chain. The working (aka second) component does contain vm.$options.__proto__.beforeUpdate.

I'm pretty new to the source code so I'm not exactly sure where we these components get extended. I'm guessing its happening in `/src/core/instance/init.js' but maybe someone more familiar can point me closer.

@despreston

This comment has been minimized.

Copy link

@despreston despreston commented Jan 13, 2020

i looked into this a little more
none of the lifecycle hooks get triggered in that first failing component
e. g 'updated' is also not triggered

Edit

It looks like the Dep being created for beforeUpdateCallCount is not being set correctly with the 'with-v-slot' component.

'my-component-with-slot' is being added as a sub to the Dep for that variable but 'with-v-slot' is not. i.e, the update to that value is not going beyond 'my-component-with-slot'

there are two separate Dep's being created for that beforeUpdateCallCount variable. so I can see it adding 'with-v-slot' as a sub, but when the actual click handler happens and the value changes, the wrong Dep is sending notifications. i can tell because this.uid in the Dep does not match the Dep that 'with-v-slot' is subscribed to

@KaelWD

This comment has been minimized.

Copy link
Contributor

@KaelWD KaelWD commented Jan 14, 2020

Is this actually a bug? with-v-slot doesn't have to re-render because scoped slots are rendered in the context of my-component-with-slot: https://jsfiddle.net/xg23ntc0/

Not calling these hooks is then correct following the lifecycle beforeUpdate -> render -> updated

This actually ties in with my feature request #9756, parents don't have to update with scoped slots so you get better performance.

@posva

This comment has been minimized.

Copy link
Member

@posva posva commented Jan 14, 2020

@KaelWD You are right, update and beforeUpdate not triggering makes sense as the only one updating is the inner component now (which is an improvement).
In order to know if the component content has changed we can listen to the hook: <my-component-with-slot @hook:beforeUpdate="beforeUpdate">

@WofWca

This comment has been minimized.

Copy link
Author

@WofWca WofWca commented Jan 14, 2020

Sounds confusing to me.
Check out this example: https://jsfiddle.net/WofWca/smyz0d9h/ (slightly modified reproduction example).
Here I have a component with a default scoped slot. Let's say I didn't need to use its props initially, so I omitted v-slot. Then I decided to use one in the template, so I put v-slot="props".
I would not find intuitive that this would break my beforeUpdate() hook and that I also need to add @hook:beforeUpdate="beforeUpdate" to prevent this.

@posva

This comment has been minimized.

Copy link
Member

@posva posva commented Jan 14, 2020

It's because the implementation is different, like @KaelWD said, the point of #9756 is to make it consistent by making it both lazily invoked, which is more performant but also does not trigger the beforeUptade. And that aligns with how slots work in Vue 3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.