Open AlexVipond opened 2 years ago
When I was adding the section about functional components to the docs for render
functions, I did initially have a short section talking about renderless components. For various reasons I removed it from the draft that got merged.
I would class renderless components as a usage pattern, rather than as a core feature. They're also not something that beginners need to learn in their first few hours of using Vue. In my opinion, they would be a good cookbook topic.
Currently the docs are being rewritten on the next
branch. I imagine it'll be another month or so before that's ready, but we're avoiding making any significant changes to the existing docs until that switchover is complete. That said, if you want to work on some draft material for this topic then feel free, just be aware that it probably can't be merged until the new docs are ready.
Yeah, that makes sense to me. I'll draft something up, but wait until next
is ready for PRs.
Probably higher priority: I'll also draft an addition to the setup
function docs, so that the render function section includes an example of using context.slots
to render a slot. It was unclear to me and appears to be unclear to other people that context.slots[slotName]
is a render function that returns an array of VNodes, which means it can be returned from setup
instead of () => h(...)
.
context.slots[slotName]
is similar to a render function but it is not a render function. It does return an array of VNodes but it takes different arguments.
Even if your slot doesn't care about the arguments it's passed, you also risk losing rendering updates if you return it as a render function from setup
. So, for example, this won't work reliably:
setup (props, { slots }) {
return slots.default
}
It may appear to work but it will fail if the slot function is replaced during parent re-rendering. In the example below, notice how the v-if
gets ignored, because the child is using the initial value of slots.default
as its render function and not the current value:
To get this to work correctly, as well as to ensure the slot is passed appropriate arguments, we would need to wrap it in an actual render function:
setup (props, { slots }) {
return () => slots.default?.()
}
If you want to add a note about returning a slot without using h
, I think it might be better to put it in here:
https://v3.vuejs.org/guide/render-function.html#return-values-for-render-functions
It could follow on from the part about returning an array.
With the arrival of the composition API, renderless components have become a bit less useful—IMO, composition functions are more versatile, easier to author, and easier to consume than renderless components.
That said, renderless components are still useful in some scenarios, and there are a few tricks to setting them up in Vue 3. Proper docs would explain the use case for renderless components, and have code examples for implementation in Vue. We can look to the React render props docs for inspiration.
There's also a question of where these docs should go. They definitely fit in with the Reusability & Composition section, but could also fit as one of the last guides in the Components In-Depth section.
I'll draft these docs in the near future, but meanwhile, below is some example code for anyone who might be looking. Here's an SFC playground for it.
Couple things to note in the code below:
setup
function. Write all your component logic insetup
with the composition API, then return your render function fromsetup
at the end.script setup
, as far as I can tell. Probably not that much of a downside, since people using render functions are usually writing components in plain.js
or.ts
files instead of.vue
files.Rendering a normal slot with a Vue template
Rendering a scoped slot with a Vue template
Rendering a normal slot with a render function returned from
setup
Rendering a scoped slot with a render function returned from
setup