composition-api: context.slots is empty in setup()
I’m not sure if this is an issue or I’m doing something wrong, but currently I got “context.slots” an empty object in setup(), although it’s available in lifecycle hook functions
import { onMounted, createElement as h } from '@vue/composition-api'
export default {
name: 'HelloWorld',
props: {
msg: String
},
setup(props, context) {
console.log(context.slots) // EMPTY OBJECT HERE
onMounted(() => {
console.log(context.slots) // SLOTS AVAILABLE HERE
})
return () => <div class="hello">{slots.default}</div>
}
}
The thing is, I need {slots.default} for render function / JSX inside setup(), so I can’t use this.$slots.default either since “this” is not available in setup().
If I try to destruct context to { slots } then it even empty inside onMounted function
import { onMounted, createElement as h } from '@vue/composition-api'
export default {
name: 'HelloWorld',
props: {
msg: String
},
setup(props, { slots }) {
console.log(slots) // EMPTY OBJECT HERE
onMounted(() => {
console.log(slots) // ALSO EMPTY HERE
})
return () => <div class="hello">{slots.default}</div>
}
}
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 16 (6 by maintainers)
@hiendv I discussed with @liximomo yesterday and we are going to duplicate
$scopedSlots
resolution logic in this plugin instead of changing Vue 2.x core, because changing the latter will create a hard Vue core version requirement for this plugin.In Vue 3 - yes, slots are resolved before
setup
.Getting
slots
from render function arguments should workPer spec:
context.slots
object should be an object that proxies to the actual slots objectcontext.slots
to work with destructuring, instead of proxyingcontext.slots
access, we need to proxy each property access oncontext.slots
.$scopedSlots
beforesetup()
is called (this may require changes in Vue core 2.x itself)context.slots
{ foo, bar } -> { bar, baz }
. This should be rare)Disclaimer: This is my own perspective of the issue as a developer who works with
$slots
and its friends a lot.So from my understanding, there are three questions here:
context.slots
is empty at first?context.slots
insetup
if you can’t use it?Well, as @liximomo already stated, the
context.slots
is a proxy ofvm.$scopedSlots
which means that the problem you are facing is not actually relevant to composition-api. Why not? Because you would have the same problem if you write the component without @vue/composition-api.You are trying to use
$scopedSlots
but they are not reactive. Imagine you write the component in the common way, the value ofthis.$scopedSlots
before rendering would be the same. So how do you solve your problem in question 3? I will come back to this later.context.slots
is empty because it’s not loaded yet.context.slots
is the reflection ofvm.$scopedSlots
. They are in thecontext
because they are supposed to. They are not forrender
only, don’t get this wrong. There are usecases and yes, you can definitely use it.Nuff said, how to separate rendering & the setup stuff? Try to solve this instead: How to separate
vm.$slots
related stuff from the rendering, they are not reactive right? Define a “ghost” copy of$slots
indata
and take the advantage of reactivity with it.Let’s say I want to have a component
Foobar
which renders attributes of slots, but only for<div/>
slots. (I know, it sounds dull 🤣)The “normal” way
The composition way
As you can see,
context.slots
is a reflection ofvm.$slots
($scopedSlots
). It should be in thecontext
object. That is my two cents.