Skip to content

Instantly share code, notes, and snippets.

@AlexVipond
Last active April 14, 2024 17:32
Show Gist options
  • Save AlexVipond/b174a7e5ceff0ec7d5b537aac647278c to your computer and use it in GitHub Desktop.
Save AlexVipond/b174a7e5ceff0ec7d5b537aac647278c to your computer and use it in GitHub Desktop.
Scoped slots in Vue 3 setup functions

Scoped slots in Vue 3 setup functions

TL;DR: You can use arrow functions that return slot function calls to render scoped slots in the render function returned by setup. Here's an SFC playground demonstrating the concept.


As of November 2021, the Vue 3 docs explain:

What's currently missing:

  • How to render scoped slots in a render function inside the setup function

Took some tinkering to figure this out, but here's the trick:

// WithScopedSlot.ts
import { ref } from 'vue'

export const WithScopedSlot = {
  setup (props, { slots }) {
    const count = ref(0)
    
    // Usually, we use `h(...)` to build and return VNodes. But the
    // `slots` render functions also return VNodes, so if we're building
    // a renderless component, we can omit `h(...)` entirely.
    // 
    // Instead, we can just return an arrow function that returns a called slot:
    return () => slots.default({
      count: count.value,
      onClick: () => count.value++,
    })
  }
}

This is handy, because it allows you to take full advantage of the Composition API via the setup function, without sacrificing the flexibility of scoped slots and renderless components.

When you consume the component, you can use the scoped slot exactly as you normally would:

<!-- MyComponent.vue -->
<script>
import { WithScopedSlot } from './WithScopedSlot'

export default {
  components: { WithScopedSlot }
}
</script>

<template>
  <WithRenderFn v-slot="{ count, onClick }">
    <div style="display: flex; gap: 1rem;">
      <span>count is: {{ count }}</span>
      <button :onClick="onClick">
        Count up
      </button>
    </div>
  </WithRenderFn>
</template>
@snimavat
Copy link

How can we support multiple slots with renderless component ?

@AlexVipond
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment