-
-
Notifications
You must be signed in to change notification settings - Fork 8k
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/updated not triggered on component when slot content in child component changes #4686
Comments
This is expected behavior in Vue 3 since the parent component in this case did not update, which is a form of optimization. |
Thank you, the workaround is suitable for my use case. I understand the need for the optimisation, but the behaviour seems unintuitive to me - it looks like the component is being updated (ref callbacks are being called in the component's scope), and yet the update hooks aren't called on that component. In my mind the component is being updated, the fact that the content is in a slot (and therefore inside a child component) is something I shouldn't need to worry about. I don't think it's too uncommon to have refs within slotted content. Here's a basic example using Vuetify which has a number of container components such as |
The slot behavior that you find unintuitive exists in order to improve on one of the more common perf problems in Vue 2 applications: slots updates forcing a chain of ancestor components to re-render even though only the slot content is affected. Bu running the slot rendering in the child component, instead of the parent, we can collect reactive dependencies in the slot as dependencies of the child's template instead of the parent's, meaning the child can re-render independently when reactive data (only) in the slot changed. We will definitely keep this behavior (which already existed in the form of "scoped slots" in Vue 2). We can consider how to make refs on v-for more ergonomic, and yes, at least document the vnode hook pattern in the docs. @yyx990803 wouldn't a vnode hook on the component itself also work, or are there edge cases that I#m missing? <template>
<slot-comp @vnode-before-update="refs.length = 0">
<h3>{{name}}</h3>
<div v-for="v in store.vals" :ref="(r) => { if (r) refs.push(r); }">Component #{{v}}</div>
</slot-comp>
</template> |
I'd also document the need to hoist For example, the following will not work as the slot-a
slot-b
app
You'd need to hoist slot-a
app
Or, construct a generic wrapper to capture updates: slot-events
app
As I build slotted components derived from others, I'm using the latter pattern to maintain composability. I don't want to preemptively guess where I need to hoist. Or, rely on the happenstance of an immediate parent where Although, this complicates styling.
|
It looks like support for array refs was added back in with commit 41c18ef, which fixes the difficulties with array refs as it's no longer necessary to use function refs for them. Closing this issue as the slot |
Version
3.2.19
Reproduction link
sfc.vuejs.org/
Steps to reproduce
NoSlot.vue
andWithSlot.vue
are identical aside from the use of a slot component inWithSlot.vue
What is expected?
Both the no-slot and with-slot components should output the same result. The
onBeforeUpdate
andonUpdated
triggers fire on both components.What is actually happening?
The no-slot component behaves as expected, but the with-slot component is never firing its
onBeforeUpdate
hook, causing the ref array to never get emptied.I am migrating a code base from Vue 2. The application makes heavy use of array refs and slots, and I would have expected the solution provided in the migration guide to give me the same behaviour as Vue 2. However,
beforeUpdate
is not called on the parent component when the slot content changes, even though the template belongs to the parent component and it is rendered in the scope of the parent component. This means the the array ref is never being emptied and continues to grow with each update.If this is expected behaviour, then a method to get an array ref when the child elements are inside a slotted component should be added to the documentation or migration guide.
The text was updated successfully, but these errors were encountered: