JAVASCRIPT
Empowering Component Reusability with Vue 3 Scoped Slots
Utilize Vue 3 scoped slots to pass data from a child component to its parent's slot content, enabling highly flexible and customizable component structures.
// MyListComponent.vue
<template>
<ul class="list-container">
<li v-for="(item, index) in items" :key="index" class="list-item">
<!-- Default content if no slot is provided, or fallback -->
<slot name="item" :item="item" :index="index">
{{ item.name || item }}
</slot>
</li>
</ul>
</template>
<script setup>
import { defineProps } from 'vue';
const props = defineProps({
items: {
type: Array,
required: true,
},
});
</script>
<style scoped>
.list-container {
list-style: none;
padding: 0;
}
.list-item {
padding: 10px;
margin-bottom: 5px;
background-color: #f0f0f0;
border-radius: 4px;
}
</style>
// App.vue
<template>
<div>
<h3>Shopping List:</h3>
<MyListComponent :items="shoppingItems">
<template #item="{ item, index }">
<span>{{ index + 1 }}. <strong>{{ item.name }}</strong> (Qty: {{ item.quantity }})</span>
</template>
</MyListComponent>
<h3>Plain List:</h3>
<MyListComponent :items="plainItems" />
</div>
</template>
<script setup>
import { ref } from 'vue';
import MyListComponent from './MyListComponent.vue';
const shoppingItems = ref([
{ id: 1, name: 'Apples', quantity: 3 },
{ id: 2, name: 'Milk', quantity: 1 },
{ id: 3, name: 'Bread', quantity: 2 },
]);
const plainItems = ref([
'Task A',
'Task B',
'Task C',
]);
</script>
How it works: This snippet demonstrates the power of Vue 3 scoped slots, allowing a parent component (`App.vue`) to customize the rendering of content provided by a child component (`MyListComponent`). The `MyListComponent` provides data (`item`, `index`) through its slot, which the parent component can access using `v-slot` (shorthand `#item="{ item, index }"`). This pattern is crucial for building highly flexible and reusable components where the child manages the structure but the parent controls the display of individual items.