Understanding and Implementing Slots in Vue Components

Default Slots

A default slot is created when no name attribute is assigned to a <slot> element. It serves as the primary content injection point.

Named Slots

Named slots are defined by adding a name property. This allows a component to have multiple distribution outlets for different content peices.

Basic Implemantation Example

Parent Component (App.vue)

<template>
  <ContentWrapper>
    <!-- Using a named slot -->
    <h2 slot="header">{{ pageTitle }}</h2>
    
    <!-- Content for the default slot -->
    <p>Main content goes here</p>
  </ContentWrapper>
</template>

<script>
import ContentWrapper from './components/ContentWrapper.vue'

export default {
  components: { ContentWrapper },
  data() {
    return {
      pageTitle: 'Dashboard'
    }
  }
}
</script>

Child Component (ContentWrapper.vue)

<template>
  <div class="container">
    <header>
      <slot name="header">Default Header</slot>
    </header>
    <main>
      <slot>Fallback content if nothing is provided</slot>
    </main>
  </div>
</template>

Scoped Slots

Scoped slots allow child componants to pass data back up to the parent rendering the slot. This is useful for customizing the layout of list items or complex data structures.

Parent Component (App.vue)

<template>
  <TaskList :items="taskList">
    <template v-slot:default="slotProps">
      <div :style="{ opacity: slotProps.item.completed ? 0.5 : 1 }">
        Task #{{ slotProps.index + 1 }}: {{ slotProps.item.text }}
      </div>
    </template>
  </TaskList>
</template>

<script>
import TaskList from './components/TaskList.vue'

export default {
  components: { TaskList },
  data() {
    return {
      taskList: [
        { id: 'a1', text: 'Learn Vue', completed: true },
        { id: 'b2', text: 'Build App', completed: false },
        { id: 'c3', text: 'Deploy', completed: false }
      ]
    }
  }
}
</script>

Child Component (TaskList.vue)

<template>
  <ul>
    <li v-for="(item, idx) in items" :key="item.id">
      <!-- Attributes bound here are available in the parent scope -->
      <slot :item="item" :index="idx"></slot>
    </li>
  </ul>
</template>

<script>
export default {
  props: {
    items: {
      type: Array,
      required: true
    }
  }
}
</script>

Tags: Vue.js Slots Scoped Slots Component Architecture Named Slots

Posted on Fri, 04 Sep 2026 16:40:39 +0000 by einhverfr