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

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

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

```Vue: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）
問題のコード

```Vue: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>
```

```json: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が生成されていない？

```Vue: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>
```

```json: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/'だけ文字列で入力し、画像名だけ変数で呼び出すことができました。

```Vue: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>
```

```json: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つのディレクトリの違いをもっと早く調べていればよかった。

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