rawHTMLを挿入する尤もらしい方法


#1

Vueもjsも初心者です。何か見当違いなことを聞いていたらごめんなさい。

以下のように、mediumというURL文字列を元に、その内容次第で場合分けしてタグを挿入するフィルタsetImgAndVideoを書きました。そしてフィルタ適用後のタグを評価したいのですが…この書き方ではタグも文字列として表示されてしまいます。
v-htmlに無理やりフィルタを適用させてなんとかする方法などがWebで見つかりましたが、それはVueの思想のようなものから逸脱してそうな無理した処理に見えて、となると根本から考え方が間違っているのではないかと思いました。このようなことをやりたい場合、どういった処理を書くのが尤もらしいでしょうか?

        <div class="in-pict" v-for="(medium, index) in tweet.media" :key="index">
          {{ medium | setImgAndVideo }}
        </div>
  filters: {
    setImgAndVideo: function(url) {
      const mediaExt = url.split(".").pop()
      const imgExts = ["jpg", "jpeg", "png", "gif"]
      if (imgExts.indexOf(mediaExt) >= 0)
        return '<a href="' + url + '" target="_blank"><img src="' + url + '"></a>'
      else
        return '<video preload="metadata" src="' + url + '" controls width="200px" height="200px"></video>'
    }
  }

#2

vue の思想とか気にせず使ってるだけなので理想的ではないかもしれませんが、

私なら html を文字列で生成するのは嫌なので、mime-type 毎に component を用意します。

  1. filename から mime-type を調べる
  2. mime-type に合わせて動的に component を表示させる

#3

返信ありがとうございます。
mime-typeを調べて動的にコンポーネントを表示させる、とても興味深いお話でした。
ただ今回は私のやりたいことだとmime-typeを調べるための通信を多数行う必要が出てくるので、見送りました。
代わりにコンポーネントを用意する、をヒントに以下のような小さなコンポーネントを書いて解決しました。

<template>
  <div v-if="isImg">
    <a :href="url" target="_blank"><img :src="url"></a>
  </div>
  <div v-else>
    <video preload="metadata" :src="url" controls width="200px" height="200px"></video>
  </div>
</template>

<script>
export default {
  props: {
    url: {
      type: String
    }
  },
  computed: {
    isImg: function() {
      const mediaExt = this.url.split(".").pop()
      const imgExts = ["jpg", "jpeg", "png", "gif"]
      return imgExts.indexOf(mediaExt) >= 0
    }
  }
}
</script>