Vue.js assets file path when using v-for

Tags: , , , ,



I’ve just started using Vue.js, it’s simple enough accessing the assets folder when loading a static img such as my logo:

<img src="../assets/logo.png">

however, I’m using v-for to create several list items using sample data, this is my template:

<ul>
    <li v-for="item in items" :key="item.id">
       <img v-bind:src="item.img" v-bind:alt="item.title">
       <h2 class="md-title">{{item.title}}</h2>
    </li>
</ul>

and this is the sample data declared within the same .vue file:

export default {
  name: 'front',
  data () {
    return {
      items: [
        {title: 'Google Pixel', img: '../assets/pixel.png', id: 1},
        {title: 'Samsung Galaxy S8', img: '../assets/s8.png', id: 2},
        {title: 'iPhone 7', img: '../assets/iphone.png', id: 3}
      ]
    }
  }
}

My problem is that the imgs all 404 which seems weird since the same path works on static imgs. If I use an absolute path such as this it works

https://media.carphonewarehouse.com/is/image/cpw2/pixelBLACK?$xl-standard$

Having looked through the documentation I found this https://vuejs-templates.github.io/webpack/static.html

Which might explain it but I’ve tried each method suggested without any luck:

Asset Resolving Rules

  • Relative URLs, e.g. ./assets/logo.png will be interpreted as a module dependency. They will be replaced with an auto-generated URL based on your Webpack output configuration.

  • Non-prefixed URLs, e.g. assets/logo.png will be treated the same as the relative URLs and translated into ./assets/logo.png.

  • URLs prefixed with ~ are treated as a module request, similar to require(‘some-module/image.png’). You need to use this prefix if you want to leverage Webpack’s module resolving configurations. For example if you have a resolve alias for assets, you need to use to ensure that alias is respected.

  • Root-relative URLs, e.g. /assets/logo.png are not processed at all.

is this an issue with webpack instead of vue? it seems crazy that a library which is so easy to use would make something like filepaths complex.

Answer

I posted this question on Vue.js’ forum and Linus Borg got back to me with the answer:

Those explanations only refer to asset paths used in HTML or CSS. in these, the respective webpack-loaders can recognize those paths and manage them.

But if you have paths in your Javascript, webpack cannot infer that those strings should be treated as paths (it can’t “understand” your program and see that those strings will later be used in HTML), so you have to tell webpack explicitly that those strings are indeed paths to dependencies, by using require().

export default {
  name: 'front',
  data () {
    return {
      items: [
        {title: 'Google Pixel', img: require('../assets/pixel.png'), id: 1},
        {title: 'Samsung Galaxy S8', img: require('../assets/s8.png'), id: 2},
        {title: 'iPhone 7', img: require('../assets/iphone.png'), id: 3}
      ]
    }
  }
}


Source: stackoverflow