Slots in Vue.js are a powerful feature that allows you to create flexible and reusable components. They enable you to pass content from a parent component to a child component, making it possible to design components that can be customized by the parent.

Key Concepts

  1. Default Slot: The simplest form of slot, where the content is passed directly into the child component.
  2. Named Slots: Allow you to define multiple slots with different names, enabling more complex content distribution.
  3. Scoped Slots: Provide a way to pass data from the child component back to the parent, allowing for more dynamic and flexible content rendering.

Default Slot

Example

Let's start with a basic example of a default slot.

Parent Component (App.vue):

<template>
  <div id="app">
    <child-component>
      <p>This is some content passed to the child component.</p>
    </child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
};
</script>

Child Component (ChildComponent.vue):

<template>
  <div class="child">
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent'
};
</script>

Explanation

  • The <slot></slot> tag in the ChildComponent.vue acts as a placeholder for the content passed from the parent component.
  • The content inside the <child-component> tags in App.vue will be rendered inside the <slot> in ChildComponent.vue.

Named Slots

Example

Named slots allow you to define multiple slots with different names.

Parent Component (App.vue):

<template>
  <div id="app">
    <child-component>
      <template v-slot:header>
        <h1>This is the header content.</h1>
      </template>
      <template v-slot:footer>
        <p>This is the footer content.</p>
      </template>
    </child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
};
</script>

Child Component (ChildComponent.vue):

<template>
  <div class="child">
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent'
};
</script>

Explanation

  • Named slots are defined using the name attribute in the <slot> tag.
  • In the parent component, the v-slot directive is used to specify which content goes into which named slot.

Scoped Slots

Example

Scoped slots allow you to pass data from the child component back to the parent.

Parent Component (App.vue):

<template>
  <div id="app">
    <child-component>
      <template v-slot:default="slotProps">
        <p>{{ slotProps.message }}</p>
      </template>
    </child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
};
</script>

Child Component (ChildComponent.vue):

<template>
  <div class="child">
    <slot :message="message"></slot>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent',
  data() {
    return {
      message: 'Hello from the child component!'
    };
  }
};
</script>

Explanation

  • The child component passes data to the slot using the v-bind syntax (:message="message").
  • The parent component accesses this data using the v-slot directive with a slot props object (v-slot:default="slotProps").

Practical Exercise

Task

Create a parent and child component where the child component has a default slot, a named slot for a header, and a scoped slot that passes a message back to the parent.

Solution

Parent Component (App.vue):

<template>
  <div id="app">
    <child-component>
      <template v-slot:header>
        <h1>This is the header content.</h1>
      </template>
      <template v-slot:default="slotProps">
        <p>{{ slotProps.message }}</p>
      </template>
    </child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
};
</script>

Child Component (ChildComponent.vue):

<template>
  <div class="child">
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot :message="message"></slot>
    </main>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent',
  data() {
    return {
      message: 'Hello from the child component!'
    };
  }
};
</script>

Explanation

  • The child component has a named slot for the header and a scoped slot that passes a message back to the parent.
  • The parent component provides content for both the named slot and the scoped slot, displaying the message from the child component.

Conclusion

Slots in Vue.js provide a powerful way to create flexible and reusable components. By understanding and utilizing default slots, named slots, and scoped slots, you can design components that are highly customizable and adaptable to various use cases. This knowledge will be essential as you progress to more advanced topics in Vue.js.

© Copyright 2024. All rights reserved