I am conditionally rendering a child component using render function. Here is an example of the parent component with the child component:
<Parent :index="1">
<Child> ... </Child>
<Child> ... </Child>
<Child> ... </Child>
</Parent>
in the render function of Parent
component, I have the following code to conditionally render the child component like this:
return () => {
const content = slots.default?.();
const children = content?.filter(child => child.type === Child);
const childToRender = children?.[props.index] ?? h('div')
return h('div', {}, () => [childToRender]);
}
the code is working as expected.
However, I would like to wrap one of the child component with another component. For example like this:
<Parent :index="1">
<Child> ... </Child>
<ChildWrapper> ... </ChildWrapper>
<Child > ... </Child>
</Parent>
where ChildWrapper.vue
looks like this:
<template>
<Child> <slot/> </Child>
</template>
which evidently the filter function (content?.filter(child => child.type === Child)
) will not pick up the Child
component in the ChildWrapper
component.
If I inspect the ChildWrapper VNode's children property, it shows an object (with the default slot function) instead of an array with Child
component which I expected. So my question is how do I get hold of the nested Child
component?
Say the parent component is a Tab
or a Carousel
component and the child component is a TabItem
or CarouselItem
component. The reason I made a ChildWrapper
component is to extend/override some of the props in the default Child
component. The parent and child components are from a component library, and it has no knowledge of what ChildWrapper
is, so the parent component can't control how ChildWrapper
should render.
I believe that obtaining specific, deeply nested child components directly from the parent is not a recommended approach. Child components may be nested deeply, beyond just one level.
Using provide
and inject
allows you to achieve your goal seamlessly, in my opinion.
I will provide a simple example to illustrate this.
Parent component:
import { provide, ref } from 'vue'
const id = -1;
const current = ref(0)
function getId() {
id++;
return id;
}
provide('provide-key', {
getId,
current
})
Child component:
import { inject,computed } from 'vue'
const { getId, current } = inject('provide-key');
const id = getId();
const isShow = computed(() => id === current.value);
The provided code is not complete, but I believe the main idea is conveyed.