2
1

More than 1 year has passed since last update.

Vue.jsでjsonから画像が取得できないときのパスの設定方法

Last updated at Posted at 2022-03-24

#はじめに
Vue CLI バージョン3で画像をどこのフォルダに入れるかで悩みました。通常のimgタグではsrc/assetsで問題ありませんが、jsonから呼び出すときに画像が表示出来なくなりました。
結論から言うと、publicに入れることで、どこからでも呼び出しができるようになりました。

#assetsに入れる場合
Googleで検索すると、assetsに入れる例がたくさん出てくるので、まずはこの方法で実装していました。

src/App.vue
// src/assets/imagesに画像を格納

// src/App.vue
<template>
  <img src="@/assets/img1.png"/>

  <div v-for="(item, i) in topImages" :key="i">
    <img :src="item.src"/>
  </div>
</template>

<script>
export default {
  data() {
    return {
     topImages: [
       { src: require('@/assets/images/top1.png') },
       { src: require('@/assets/images/top2.png') }
      ]
    }
  }
}
</script>

scriptで取得する場合もrequireを使って呼び出すことで問題なく表示できます。

しかし、この画像パスをjsonファイルに書いて呼び出すことが出来ませんでした。

#jsonに画像パスを書いた場合(失敗1)
問題のコード

src/App.vue
// src/assets/imagesに画像を格納

<template>
  <div v-for="(item, i) in members" :key="i">
    <img :src="item.image_url"/>
  </div>
</template>

<script>
export default {
  data() {
    return {
     members: []
    }
  },
  created() {
    this.axios.get('members.json')
      .then(function (response) {
        this.members = response.data
      }.bind(this)).catch(function (e) {
        console.error(e)
      })
  }
}
</script>
src/members.json
[
  {
    "image_url": "@/assets/images/img1.png",
  }
  {
    "image_url": "@/assets/images/img2.png",
  }
  {
    "image_url": "@/assets/images/img3.png",
  }
]

この状態だと、ブラウザ上に画像が表示されません。(Chromeだと山のマークになる)
検証ツールで確認すると、<img src="@/assets/images/img1.png">になります。
パスではなく、文字列としてそのまま呼ばれてしまっています。

#jsonに画像パスを書いた場合(失敗2)
'@/assets/images/'のみ文字列で固定し、画像名だけ読み込もうとしましたが、こちらはブラウザだけでなく検証ツールにも反映されませんでした。DOMが生成されていない?

src/App.vue
// src/assets/imagesに画像を格納

<template>
  <div v-for="(item, i) in members" :key="i">
    <img :src="'@/assets/images/' + item.image_url"/> // ←変更
  </div>
</template>

<script>
export default {
  data() {
    return {
     members: []
    }
  },
  created() {
    this.axios.get('members.json')
      .then(function (response) {
        this.members = response.data
      }.bind(this)).catch(function (e) {
        console.error(e)
      })
  }
}
</script>
src/members.json
[
  {
    "image_url": "img1.png", // ←変更
  }
  {
    "image_url": "img2.png",
  }
  {
    "image_url": "img3.png",
  }
]

#jsonに画像パスを書いた場合(失敗3)
失敗2と全く同じコードのまま、members.jsonファイルをsrcからpublicフォルダへ移動させました。
この場合は、失敗1と同じ現象が起こり、画像は表示されませんでした。

#jsonに画像パスを書いた場合(成功)
結局、画像もjsonも全てpublicフォルダへ移動することで解決しました。
'images/'だけ文字列で入力し、画像名だけ変数で呼び出すことができました。

public/App.vue
// public/assets/imagesに画像を格納

<template>
  <div v-for="(item, i) in members" :key="i">
    <img :src="'images/' + item.image_url"/> // ←変更
  </div>
</template>

<script>
export default {
  data() {
    return {
     members: []
    }
  },
  created() {
    this.axios.get('members.json')
      .then(function (response) {
        this.members = response.data
      }.bind(this)).catch(function (e) {
        console.error(e)
      })
  }
}
</script>
public/members.json
[
  {
    "image_url": "img1.png",
  }
  {
    "image_url": "img2.png",
  }
  {
    "image_url": "img3.png",
  }
]

#src/assets と public どちらに配置すべきか
###src/assets の特徴
・base64形式で画像が出力されるため、HTTPリクエストの発生を減らすことが出来る。
・webpackでコンパイルできる
・キャッシュされない

###public の特徴
・webpackでコンパイルされない
・CSSのbackground-imageで利用する場合は必ず画像をpublicに入れる必要がある

###参考サイト
https://webrandum.net/vue-cli-image-path/

#おわりに
jsonに画像パスを書いてaxiosで呼び出すことなどあまりないと思いますが、フロントだけの実装練習の時に使用しました。
以前もbackground-imageで画像を参照できずにpublicを使用しましたが、jsonでもpublicを使用する必要があったようです。2つのディレクトリの違いをもっと早く調べていればよかった。

解決に時間がかかった理由のひとつに、検索してもassetsstaticの比較ばかり出てくるのですが、このstaticフォルダが何のことだか分からなかった事があります。VueCLIバージョン2でstaticだったものが、バージョン3で名前が変わりpublicになったようです。

2
1
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
2
1