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
$scopedSlotsresolution 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
slotsfrom render function arguments should workPer spec:
context.slotsobject should be an object that proxies to the actual slots objectcontext.slotsto work with destructuring, instead of proxyingcontext.slotsaccess, we need to proxy each property access oncontext.slots.$scopedSlotsbeforesetup()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
$slotsand its friends a lot.So from my understanding, there are three questions here:
context.slotsis empty at first?context.slotsinsetupif you can’t use it?Well, as @liximomo already stated, the
context.slotsis a proxy ofvm.$scopedSlotswhich 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
$scopedSlotsbut they are not reactive. Imagine you write the component in the common way, the value ofthis.$scopedSlotsbefore rendering would be the same. So how do you solve your problem in question 3? I will come back to this later.context.slotsis empty because it’s not loaded yet.context.slotsis the reflection ofvm.$scopedSlots. They are in thecontextbecause they are supposed to. They are not forrenderonly, 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.$slotsrelated stuff from the rendering, they are not reactive right? Define a “ghost” copy of$slotsindataand take the advantage of reactivity with it.Let’s say I want to have a component
Foobarwhich 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.slotsis a reflection ofvm.$slots($scopedSlots). It should be in thecontextobject. That is my two cents.