7
6

More than 5 years have passed since last update.

vue.jsのtemplateでsvgのimageタグ使うときに気をつける話

Last updated at Posted at 2014-12-19

vue.js@0.11.2以上ではrepeatするcomponentをtemplate化しないとけないということがわかったので子要素をtemplate化したはいいものの、svgをtemplateにしたことでまた微妙な問題を踏んでしまった。

<image><img>にされるよ!

<svg><image>を使うようなコンポーネントを作りたかったのでこんな感じでやると

<html>
  <body>
    <svg id="sample">
      <g v-repeat="items" v-component="item"></g>
    </svg>
    <template id="item" >
      <image width=50 height=50 v-attr="'xlink:href': v"></image>
    </template>
    <script src="build.js"></script>
  </body>
</html>
var Vue = require("vue")
Vue.component("item", {  
  template : "#item",
})

var app = new Vue({
  data: {   
    items : [
      {v : "http://cdn.qiita.com/assets/siteid-reverse-cd0519106e5814e34d402b3e821820cf.png"},
    ]
  },
  methods: {
  }
})

app.$mount("#sample")

↓こんな感じになってしまった。

output.html
<g>
  <img width="50" height="50" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://cdn.qiita.com/assets/siteid-reverse-cd0519106e5814e34d402b3e821820cf.png">
</g><!--v-repeat-->

ぶへ。なんでー。
となったが割りとさっくり解決できた。

解法1: templateに直接stringで書く

いや。これはちょっと個人的には微妙。

Vue.component("item", {  
  template : '"<image width=50 height=50 v-attr="\'xlink:href\': v"></image>"',
})

解法2: scriptタグで書く。

というかやっていてそもそも<template>を使うとかいきがったことをしているから悪かった。
(そもそも<template>使うのいいんだっけ?となったけどこのPull Requestで取り込まれているので問題なさそう)

なので<script>で記述すれば問題なかった。

    <script type="x-template" id="item" >
      <image width=50 height=50 v-attr="'xlink:href': v"></image>
    </script>

解法3: templateの親要素をsvgにする

他には親要素をsvgにすればちゃんと出てくれる

<svg id="item" ><!-- display:noneはサンプルなので省略 --> 
   <image width=50 height=50 v-attr="'xlink:href': v"></image>
</svg>

解法4: templateにnamespaceをつける

更にこんなんでもOKそう。

    <template id="item" xmlns="http://www.w3.org/2000/svg">
      <image width=50 height=50 v-attr="'xlink:href': v"></image>
    </template>

どういうことか。

これはvueの話ではなくブラウザ側の挙動の問題の模様。
(chromeで調査したので他だとどうなるかは未調査です)

こんなサンプルを用意すると、以下のような出力がされる。

<div id="foo">
  <image></image>
</div>
<script>
  console.log(document.querySelector("#foo").innerHTML)
</script>
<img>

つまりvueがこれと同じようなことをしていて、chromeさんがparseする段にsvgとみなせないような<image>タグを<img>として扱ったということだろう

ちゃんとした検証はしていないが解法2が一番カバー率が高いのではと思っている。

ちなみにxlink:hrefのはなし。

「あれ、v-attrにxlink:hrefって使えなくね?」って思ったけど
このissueにすでに上がっていてv-attr="'xlink:href':urlにすればよいよーと言われていた。

助かった。

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6