Skip to content

Instantly share code, notes, and snippets.

@Akryum
Last active Jun 27, 2022
Embed
What would you like to do?
Vue 3: Detect content inside slots
<!-- Doesn't work with Vue 2 scoped slots nor Vue 3 slots in some cases -->
<template>
<div>
<div v-if="$slots.foo">
<slot name="foo" title="Title" />
</div>
</div>
</template>
<script>
import { getSlotContent } from './slot.js'
export default {
computed: {
fooSlot () {
return getSlotContent(this.$slots.foo?.({ title: 'Title' }))
},
FooSlot () {
return () => this.fooSlot
},
},
}
</script>
<template>
<div>
<div v-if="fooSlot">
<component :is="FooSlot" />
</div>
</div>
</template>
<script setup>
import { computed, useSlots } from 'vue'
import { getSlotContent } from './slot.js'
const slots = useSlots()
const fooSlot = computed(() => getSlotContent(slots.foo?.({ title: 'Title' })))
const FootSlot = () => fooSlot.value
</script>
<template>
<div>
<div v-if="fooSlot">
<FooSlot />
</div>
</div>
</template>
import { isVNode, Comment, Fragment } from 'vue'
// from https://github.com/vuejs/core/blob/main/packages/runtime-core/src/helpers/renderSlot.ts#L84-L97
export function getSlotContent(vnodes) {
if (!vnodes) return null
return vnodes.some(child => {
if (!isVNode(child)) return true
if (child.type === Comment) return false
if (
child.type === Fragment &&
!getSlotContent(child.children)
) return false
return true
})
? vnodes
: null
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment