·
1 min read

Vue Tip: Use Scoped Slots in a Child Component to Provide Data for Parent Component

MH

Michael Hoffmann

@mokkapps

Vue Tip: Use Scoped Slots in a Child Component to Provide Data for Parent Component Image

Slots are mighty, but they are not almighty. For example, slot content does not have access to the state in the child component.

There are cases where you want to provide data for presentation in the parent component. For that, you can use Scoped Slots.

Using scoped slots, a child component can pass data to a slot when rendering it:

Child.vue
<script setup lang="ts">
import { ref } from 'vue'

const firstName = ref('Michael')
const lastName = ref('Hoffmann')
</script>

<template>
  <div>
    <slot :first-name="firstName" :last-name="lastName" />
  </div>
</template>

Let's first take a look at receiving props using a single default slot first. For this, we can use the v-slot directive on the child component tag:

Parent.vue
<template>
  <Child v-slot="slotProps">Name: {{ slotProps.firstName }} {{ slotProps.lastName }}</Child>
</template>

The following graphic illustrates the process of passing props from the child to the parent component:

Scoped Slots

You can think of a scoped slot as a function passed into the child component. The child component then calls it, passing props as arguments:

The above code almost represents how Vue compiler compiles scoped slots and how you would use them in manual render functions.

As v-slot="slotProps" matches the slot function signature, you can destructure the object in v-slot:

Parent.vue
<template>
  <Child v-slot="{ firstName, lastName }">Name: {{ firstName }} {{ lastName }}</Child>
</template>

Of course, you can also use scoped slots with named slots:

Parent.vue
<template>
  <Child>
    <!-- Explicit default slot -->
    <template #default="{ firstName, lastName }">
      <p>Name: {{ firstName }} {{ lastName }}</p>
    </template>

    <!-- Named slot -->
    <template #footer="{ message }">
      <p>{{ message }}</p>
    </template>
  </Child>
</template>
The code for this demo is interactively available at StackBlitz:

If you liked this Vue tip, follow me on BlueSky to get notified about new tips, blog posts, and more. Alternatively (or additionally), you can subscribe to my weekly Vue & Nuxt newsletter :

I will never share any of your personal data. You can unsubscribe at any time.