4👍
Your usage of slot in Parent is incorrect. Whole point of slots is to render something the Parent knows nothing about (ie. anything you pass to it). So rendering Child
directly is wrong (as it tights Parent into always rendering Child instead of slot content)
Second problem is using const defaultSlot = slots.default();
inside the setup
– slots are functions and arguments of those functions (such as props and other reactive data from the parent scope) change when the template is re-rendered. So the slot function needs to be executed every time the Parent re-renders. But setup
runs only once. This is why you don’t see any update of Child. Instead use a slot directly in render function:
// Parent component
<script setup>
import { h, useSlots } from "vue";
const slots = useSlots();
const render = () => {
return h("div", {}, slots.default ? slots.default() : null);
};
</script>
2👍
In addition to the excellent answer provided by @Michal Levy, you can also wrap your call to default()
or any other named slot
, in a computed ref
. This will allow the lookup to be lazy, cached, callable from the standard watch function, used outside the render function, and put directly in SFC templates.
<script setup>
import { h, useSlots } from "vue";
const slots = useSlots();
const slotProps = computed(()=>slots.default ? slots.default().props : undefined)
watch(props, value), {
console.log('props', value)
}, {immediate: true})
</script>
<template>
<h1>Dynamic Slot Props</h1>
<div>{{slotProps}}
</template>