🎉

【Vue3】コンポーネントタグ入りのHTML文字列をレンダリングする方法

2022/08/12に公開

どういうときに使うのか

<router-link>などのVueコンポーネントタグを含んだHTMLをAPIから供給されたとき、v-htmlを使ってもこれらをパースすることはできません。これを回避したいときに使います。

やってみよう!

1. ラッパーを作る

まず、Vueコンポーネントタグをパースするコンポーネントを作ります。これに関してはコピペでそのまま使えます。

Wrapper.vue
<script>
import {compile, h} from 'vue/dist/vue.esm-bundler.js';
export default {
    props: {
        content: {
            type: String,
            required: true
        }
    },
    render() {
        return h(compile(this.content));
    }
};
</script>

2. 必要なところに入れる

あとは簡単です!コンテンツを出したいところにこのコンポーネントを置いて、contentプロップスに文字列を放り込んでください。

Example.vue
<script setup>
import Wrapper from 'path/to/Wrapper.vue';
</script>

<template>
    <div class="article-body">
        <Wrapper :content="post.content" />
    </div>
</template>

【おまけ】Vue 2 向けのラッパー

参考サイト

Wrapper_v2.vue
<script>
import Vue from "vue";
export default {
    props: {
        content: {
	    type: String,
	    required: true
	}
    },
    data() {
        return {
          templateRender: null,
        };
    },
    render(h) {
        if (!this.templateRender) {
          return h('div', 'loading...');
        } else {
          return this.templateRender();
        }
    },
    watch: {
        content: {
            immediate: true,
            handler() {
                var res = Vue.compile(this.content);
    
                this.templateRender = res.render;
            
                this.$options.staticRenderFns = []
            
                this._staticTrees = []
            
                for (var i in res.staticRenderFns) {
                    this.$options.staticRenderFns.push(res.staticRenderFns[i])
                }
            }
        }
    }
}
</script>

Discussion