Vue Slot Mechanism: Default, Named, and Scoped Slots

What is a Slot?

In HTML, the <slot> element (part of Web Components) acts as a placeholder with in a custom element. This placeholder is later filled with custom markup.

Example (Web Components):

<template id="element-details-template">
  <slot name="element-name">Fallback Text</slot>
</template>
<element-details>
  <span slot="element-name">Item A</span>
</element-details>
<element-details>
  <span slot="element-name">Item B</span>
</element-details>

To render this, register the custom element:

customElements.define('element-details', class extends HTMLElement {
  constructor() {
    super();
    const template = document.getElementById('element-details-template').content;
    this.attachShadow({ mode: 'open' }).appendChild(template.cloneNode(true));
  }
});

In Vue, a slot reserves a position in a component’s template. When the component is used, content inside its tag replaces the slot. Think of it like a game console (slot) for game cartridges (custom content).

Use Cases

Slots enable component extension and customization. Instead of rewriting a reusable component for minor changes, slots let you inject content into specific positions. Use cases include layout components, table columns, dropdowns, and modals.

Slot Classification

Vue slots are categorized into three types:

Default Slot

The child component uses <slot> to define a content placeholder. If the parent provides no content, the slot’s fallback is used.

Child Component (Child.vue):

<template>
  <slot>
    <p>Fallback Content</p>
  </slot>
</template>

Parent Component:

<Child>
  <div>Default Slot Content</div>
</Child>

Named Slots

Child components use the name attribute to identify multiple slots. The parent targets slots with v-slot:name.

Child Component (Child.vue):

<template>
  <slot>Default Fallback</slot>
  <slot name="content">Content Fallback</slot>
</template>

Parent Component:

<Child>
  <template v-slot:default>Default Named Slot</template>
  <template v-slot:content>Custom Content</template>
</Child>

Scoped Slots

Child components bind data to the slot (via props) so the parent can acces it. The parent uses v-slot (or #) to receive these props.

Child Component (Child.vue):

<template>
  <slot name="footer" slotData="Child Data">
    <h3>No Footer Slot</h3>
  </slot>
</template>

Parent Component:

<Child>
  <template v-slot:default="slotProps">
    Data from Child: {{ slotProps.slotData }}
  </template>
  <template #default="slotProps">
    Data from Child: {{ slotProps.slotData }}
  </template>
</Child>

Key Notes

  • v-slot is only valid on <template>, except for default slots (usable on the component tag).
  • The default slot is named default (can be omitted: v-slot instead of v-slot:default).
  • Shorthand # requires a slot name (e.g., #default).
  • Destructuring, ranaming, and defaults: v-slot="{ slotData: customName, slotData = 'default' }".

Underlying Mechanism

Slots are functions that return VNodes. Vue’s rendering flow is template → render function → VNode → DOM.

Example: Button Counter Component

Component Definition:

Vue.component('button-counter', {
  template: '<div><slot>Default Content</slot></div>'
});

Parent Usage:

new Vue({
  el: '#app',
  template: '<button-counter><span>Slot Content</span></button-counter>',
  components: { buttonCounter }
});

The render function for button-counter becomes:

(function anonymous() {
  with(this) { return _c('div', [_t("default", [_v("Default Content")])], 2); }
})

Slot Resolution Process

  1. resolveSlots: Groups child nodes by slot name (or default).
  2. normalizeScopedSlots: Creates vm.$scopedSlots for scoped data.

In resolveSlots, nodes with slot attributes are grouped:

function resolveSlots(children, context) {
  // Logic to group nodes by slot name...
  return slots;
}

Scoped slots pass data via props in renderSlot, enabling parent access to child data.

Tags: Vue.js Slots Default Slot Named Slot Scoped Slot

Posted on Mon, 08 Jun 2026 17:47:23 +0000 by gabrielserban