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 intemplate
following byv-slot:name
orwe can use shorthand #name. We may or not emit adefault
slot 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 with❤by leovoon