【Vue3】v-htmlとは?使い方を紹介する

v-htmlとは

v-htmlとは、htmlを値に指定することで、そのままhtmlとして出力してくれるディレクティブ(vue独自の属性)です。Vue3で動きます。

v-htmlは非常に自由に使える反面、セキュリティに注意が必要なディレクティブです。

v-htmlの使い方

dataに指定しているhtmlがそのまま、描画されます。

<script setup>
let html = '<h1>Page title</h1>'
</script>

<template>
  <div v-html="html" />
</template>

v-htmlはxssに注意

v-html非常に自由に使える反面、セキュリティに注意が必要なディレクティブです。

特にユーザーが入力した値をそのままv-htmlで使うのは絶対にやめましょう。 悪意のあるユーザーに悪用される恐れがあります。

<script>
  import { ref } from 'vue'
  export default {
    setup() {
      let html = ref('<h1>Page title</h1>')
      return {
        html
      }
    }
  }
</script>

<template>
  <input v-model="html" />
  <div v-html="html" />
</template>

上の例だと、inputに入力した値がそのままhtmlとして描画されてしまいます。

上の例にはv-modelが登場します。詳しくはこちら。

v-htmlで出力したhtmlにCSSをあてる

v-htmlで出力したhtmlには単一ファイルコンポーネントのscopedで設定したstyleが当たりません。v-htmlのhtmlにCSSを当てたい場合はディープセレクタというものを使う必要があります。

Deep Selectors | Scoped CSS | Vue Loader

これはうまくいかない。

<script>
  import { ref } from 'vue'
  export default {
    setup() {
      let html = ref('<h1>Page title</h1>')
      return {
        html
      }
    }
  }
</script>

<template>
  <div>
    <input v-model="html" />
    <div v-html="html" />
    <h1>Page title</h1>
  </div>
</template>

<style scoped>
h1 {
  color: red
}
</style>

これだとうまくいく。

<script>
  import { ref } from 'vue'
  export default {
    setup() {
      let html = ref('<h1>Page title</h1>')
      return {
        html
      }
    }
  }
</script>

<template>
  <div class="title">
    <input v-model="html" />
    <div v-html="html" />
    <h1>Page title</h1>
  </div>
</template>

<style scoped>
.title >>> h1 {
  color: red
}
</style>

さらにscssを使っている場合は>>>だとうまくいかないので、/deep/::v-deepと書くといいようです。