vue.jsrenderingslot

Pass render function to slot in Vue3


I have a component TopBar

<script setup lang="ts">
import { h } from 'vue';

const props = withDefaults(defineProps<{ height?: number }>(), { height: 50 });

const spacer = () => h('span', { class: 'bar__spacer' } );
</script>

<template>
  <div class="bar" :style="{ '--height': props.height }">
    <slot :spacer="spacer"></slot>
  </div>
</template>

<style scoped lang="scss">
.bar {
  position: relative;
  display: flex;
  flex: 0 0 calc(var(--height) * 1px);
  width: 100%;
  align-items: center;
  padding: 0 10px;
  background-color: var(--bg-top-bar);
  border-bottom: 1px solid var(--bg-separator);

  &__spacer {
    flex-grow: 1;
  }
}
</style>

When I'm using it, I want to add spacer as HTML element. So it'll look like this:

    <TopBar v-slot="{ spacer }">
      Some content goes here...
      <spacer/>
      Some more content there...
    </TopBar>

But it didn't work. The spacer tag renders as <spacer/>. Any way to accomplish this?


Solution

  • You can use the <component :is=""> syntax, i.e.

    <TopBar v-slot="{ spacer }">
      <component :is="spacer"/>
    </TopBar>
    

    Playground