images can't be displayed with v-bind in v-for loop

1.4k views Asked by At

I know there are a lot of questions and answers about how to use v-bind in v-for to bind to img src ... however, I spent a whole day experimenting in vain. I apologize for a duplicate question, but could anyone help me?

I am using [email protected] and @vue/cli 4.5.6. I am trying to show multiple images in v-for loop, binding file paths to img src. I have skills data in skills.json, trying to display them in Skills.vue. The code below just shows blank screen.

Any help is appreciated, thank you.

skills.json

[
  {
    "id": 1,
    "name": "C#",
    "logo": "C-Sharp.svg"
  },
  {
    "id": 2,
    "name": "Azure",
    "logo": "azure.svg"
  }
]

Skills.vue

Looking at vue developer tool, I could confirm the data is correctly imported into skills array(but not showing up).

<template>
  <div class="container">
    <div class="items">
      <div class="item" v-for="skill in skills" :key="skill.id">
        <img :src="require(`${logoPath}${skill.logo}`)" />
      </div>
    </div>
  </div>
</template>

<script>
import skillsJson from '../assets/skills.json';

export default {
    data() {
        return {
            skills: skillsJson,
            logoPath: '../assets/img/',
        };
    },
};
</script>

src folder structure

C:.
│  App.vue
│  main.js
├─assets
│  │  skills.json
│  ├─icons
│  ├─img
│  │      azure.svg
│  │      C-Sharp.svg
│  └─scss
├─components
├─router
│      index.js
└─views
        Experience.vue
        HelloWorld.vue
        Home.vue
        Skills.vue
1

There are 1 answers

1
Michal Levý On BEST ANSWER

You need to understand that require() (or import()) is handled by Webpack at build time. Webpack can't execute your code (at build time) and possibly know what the value at runtime will be. Take a look at the docs (it's about import() but require() is almost same)

Simple fix would be to make only part of the path dynamic so Webpack gets at least some hint what file should be made available...

Replace

<img :src="require(`${logoPath}${skill.logo}`)" />

by

<img :src="require(`../assets/img/${skill.logo}`)" />

TLDR

Webpack's require() needs at least some part of the file path to be completely static!