VueJS is known for its flexibility and simplicity in building component-based user interfaces. One of its most powerful features is the slot system, which allows you to compose components and pass content from parent to child. However, there are scenarios where you might want to conditionally render a component only if it has children. This is where slots.default() comes into play.

Slots are placeholders in a componentā€™s template where you can inject content. The default slot is the primary slot where content is passed by default when no named slot is specified.

Hereā€™s a simple example of a default slot:

<template>
  <div>
    <slot />
  </div>
</template>

When using this component, any content inside it will be rendered where the <slot> tag appears:

<MyComponent>
  <p>This is passed as default slot content.</p>
</MyComponent>

Sometimes, you may want to prevent a component from rendering if no content is passed to its slot. For example, you might have a wrapper component that should only appear when thereā€™s meaningful content to display.

The slots.default() function in Vue 3 provides a way to programmatically check if a default slot has content. Hereā€™s how you can use it:

  1. Access the Slots Object in the Script Section In Vue 3, the setup function allows you to access the slots object, which contains the default slot and any named slots.

  2. Check for Content You can call slots.default to check if the default slot exists and render its content.

Below is an example component written in Vue 3 with TypeScript:

<script lang="ts" setup>
const hasDefaultSlot = computed(() => {
  return !!slots.default && slots.default({}).length > 0;
});
</script>

<template>
  <div v-if="hasDefaultSlot">
    <slot />
  </div>
</template>

Key points to note:

  1. Using slots.default()

    • slots.default() returns an array of VNode objects representing the slotā€™s content.
    • If the slot is empty, slots.default() will return undefined or an empty array.
  2. Computed Property

    • The hasDefaultSlot computed property dynamically evaluates whether the default slot has content, ensuring the logic is reactive and updates as needed.

Hereā€™s how you can use the ConditionalWrapper component:

<template>
  <ConditionalWrapper>
    <p>This will be rendered because the slot has content.</p>
  </ConditionalWrapper>

  <ConditionalWrapper>
    <!-- No content passed, so this won't render. -->
  </ConditionalWrapper>
</template>