Home > OS >  Render slot as v-html (Vue 3)
Render slot as v-html (Vue 3)

Time:10-07

Goal

How to implement a component that renders an html string (eg fetched from a CMS) passed as a slot like this :

// app.vue
<script setup>
import MyComponent from "./MyComponent.vue"
const htmlStr = `not bold <b>bold</b>`
</script>

<template>
  <MyComponent>{{htmlStr}}</MyComponent>
</template>

Explanation

To render an html string (eg fetch from a CMS) we can use v-html :

// app.vue
<script setup>
const htmlStr = `not bold <b>bold</b>`
</script>

<template>
  <p v-html="htmlStr"></p>
</template>

Failed attempts

I have tried with no success :

// component.vue
<script>
import { h } from "vue";

export default {
  setup(props, { slots }) {
    return () =>
      h("p", {
        innerHTML: slots.default(),
      });
  },
};
</script>

Renders

[object Object]

Link to playground

Workaround with props

As a workaround, we can of course use props but it's verbose.

// app.vue
<template>
  <MyComponent :value="htmlStr">{{htmlStr}}</MyComponent>
</template>
// component.vue
<template>
  <p v-html="value"></p>
</template>

<script setup>
import { defineProps } from 'vue'
  
defineProps(['value'])
</script>

CodePudding user response:

slots.default() returns an array of your passed slot elements, try to map that content and render it :

h("p", {
   innerHTML: slots.default().map(el=>el.children).join(''),
  });

Playground

CodePudding user response:

You can just pass it in div v-html and remove h function:

<MyComponent>
  <div v-html="htmlStr" />
</MyComponent>
  • Related