Making reusable components using Vue Slot

Here are two reusable button components created using different types of slot methods.

The first one is a simple button. Just wrap the props from the parent component and pass them to the default slot called<slot></slot>in the child component.

// AppButton.vue
<template>
    <button>
        <slot>{{ text }}</slot>
    </button>
</template>

<script lang='ts' setup>
  const props = defineProps(['text']);
  const { text } = props
</script>
<!-- Parent.vue -->
<app-button>Cool button</app-button>

Secondly isnamed slot. We specify the name of multiple slots in child component, pass content from parent component based on the slot name set. In this example we set a fallback content of icon in slot namedicon.

<!-- AppButton2 -->
<template>
    <button>
        <slot name="icon"> <akar-icons:heart class="inline-block" /> </slot>
        <slot name="default">{{ text }}</slot>
    </button>
</template>
<!-- Parent.vue -->
<app-button2>  second button </app-button2>

For each slot we wrap it intemplatefollowing byv-slot:nameorwe can use shorthand #name. We may or not emit adefaultslot based on your preferences.

<!-- Parent.vue -->

<app-button2>
  <template v-slot:icon> 😊 </template>
  text passed to default slot
</app-button2>

<!-- shorthand -->
<app-button2>
  <template #icon>😊</template>
  <template #default>text passed to default slot</template>
</app-button2>

and they will look exactly the same like

Dynamic Scoped Slot

Sometimes we may want to switch slots dynamically based on reactive data. SelectedItem is an example of reactive data.

// Parent.vue
<template>
  <child>
   <template #[dynamicSlotName]="{ itemKey }">  // v-slot:[slotName]
      {{ itemKey }}  // item.fullname / item.firstname
   </template>
   <template #default></template>
  </child>
</templte>

<script setup>
const dynamicSlotName = ref('default')
</script>
// Child.vue
<template>
  <div v-for="item in items" :key="item.id">
    // bind dynamic value of item as props to be passed to parent
    <slot name="first" :itemKey="item.fullname"></slot> 
    <slot name="second" :itemKey="item.firstname"></slot> 
      // or  default slot
    <slot name="default" :itemKey="item"></slot> 
  </div>
</templte>

Happy learning!

Made withby leovoon