50

My Vue component contains some images. I want to do lazy-loading later, so I need to set the src of the images to a small image, first.

<template>
        <div v-for="item in portfolioItems">
            <a href="#{{ item.id }}">
                <img
                    data-original="{{ item.img }}"
                    v-bind:src="/static/img/clear.gif"
                    class="lazy" alt="">
            </a>
        </div>
</template>

Gives me a bunch of errors, like:

[Vue warn]: Invalid expression. Generated function body: /scope.static/scope.img/scope.clear.gif vue.common.js:1014[Vue

[Vue warn]: Error when evaluating expression "/static/img/clear.gif": TypeError: Cannot read property 'call' of undefined (found in component: )

webpack.config.js:
module.exports = {
    // ...
    build: {
        assetsPublicPath: '/',
        assetsSubDirectory: 'static'
    }
}

9 Answers 9

79

This solution is for Vue-2 users:

  1. In vue-2 if you don't like to keep your files in static folder (relevant info), or
  2. In vue-2 & vue-cli-3 if you don't like to keep your files in public folder (static folder is renamed to public):

The simple solution is :)

<img src="@/assets/img/clear.gif" /> // just do this:
<img :src="require(`@/assets/img/clear.gif`)" // or do this:
<img :src="require(`@/assets/img/${imgURL}`)" // if pulling from: data() {return {imgURL: 'clear.gif'}}

If you like to keep your static images in static/assets/img or public/assets/img folder, then just do:

<img src="./assets/img/clear.gif" />
<img src="/assets/img/clear.gif" /> // in some case without dot ./
Sign up to request clarification or add additional context in comments.

5 Comments

using vue-cli-3, this answer finally did it for me loading in a path string dynamically.
<img :src="require(@/assets/img/clear.gif)"> worked for me. My file structure is in /assets/img/clear.gif. Thank you for a lot of options to choose from. Finally, one worked for me.
@VinceBanzon glad that helped you, don't forget to up vote ;)
This still works with VueCLI 4.4. Thanks kind sir, you just got upvoted!! ;)
I put '@' inside of the variable. Your solution you put '@' inside the tag and the variable you put only the name of file, not path. it was great! Thank you!
51

If you want to bind a string to the src attribute, you should wrap it on single quotes:

<img v-bind:src="'/static/img/clear.gif'">
<!-- or shorthand -->
<img :src="'/static/img/clear.gif'">

IMO you do not need to bind a string, you could use the simple way:

<img src="/static/img/clear.gif">

Check an example about the image preload here: http://codepen.io/pespantelis/pen/RWVZxL

1 Comment

Your example is broken and I'm not sure if <img src="/static/img/clear.gif"> actually works as other answers clearly point out to use require('@/assets/...') for the :src prop.
22

This is how i solve it.:

      items: [
        { title: 'Dashboard', icon: require('@/assets/icons/sidebar/dashboard.svg') },
        { title: 'Projects',  icon: require('@/assets/icons/sidebar/projects.svg') },
        { title: 'Clients', icon: require('@/assets/icons/sidebar/clients.svg') },
      ],

And on the template part:

<img :src="item.icon" />

See it in action here

2 Comments

It is working.I added a sandbox example in my answer.Take a look to it.
amazing. after searching for 1 hour. Can you please also suggest why do we need @require in this specific case
10

@Pantelis answer somehow steered me to a solution for a similar misunderstanding. A message board project I'm working on needs to show an optional image. I was having fits trying to get the src=imagefile to concatenate a fixed path and variable filename string until I saw the quirky use of "''" quotes :-)

<template id="symp-tmpl">
  <div>
    <div v-for="item in items" style="clear: both;">
      <div v-if="(item.imagefile !== '[none]')">
        <img v-bind:src="'/storage/userimages/' + item.imagefile">
      </div>
      sub: <span>@{{ item.subject }}</span>
      <span v-if="(login == item.author)">[edit]</span>
      <br>@{{ item.author }}
      <br>msg: <span>@{{ item.message }}</span>
    </div>
  </div>
</template>

Comments

7

declare new variable that the value contain the path of image

const imgLink = require('../../assets/your-image.png')

then call the variable

export default {
    name: 'onepage',
    data(){
        return{
            img: imgLink,
        }
    }
}

bind that on html, this the example:

<a href="#"><img v-bind:src="img" alt="" class="logo"></a>

hope it will help

Comments

2

You need use just simple code <img alt="img" src="../assets/index.png" />

Do not forgot atribut alt in balise img

Comments

2

I had a similar issue with Vue where I tried to display several images by importing data from a configuration json file and then iterating over the data using v-for.

Even when I put require('../../assets/' + filename) right in the json, the images would never show. I eventually realized that Vue was interpreting my data value as a string, rather than a function. Good thing that javascript supports functions as a return type. So I made this function:

  getImagePath(filename: string) {
    return require('../../assets/' + filename);
  }

I then just called that function from my v-for loop simply passing in the filenames from my config:

<v-list-item :key="place.id" v-for="place in placesOfPower">
  <v-list-item-content class="justify-end">
    <v-img :src="getImagePath(place.image)"
           position="top center"
           height="90"
           width="30vw"/>
  </v-list-item-content>
<v-list-item-content>

Comments

0

I found this thread on my search for a solution to show an image when it exists. I want to show a list of database entries that contain a type property. Each type should have a fitting png file in my vue assets folder. The whole list would break if a new type would be added without adding the image beforehand.

I found "Catch an error on requiring module in node.js" on stack overflow. The answer by Peter Lyons led me to my solution:

<template>
  <v-data-table :items="items">
    <template v-slot:item.type="{ item }">
      <v-img
        v-if="typeImageSource(item.type)"
        :src="typeImageSource(item.type)"
      />
      <template v-else>
        {{ item.type }}
      </template>
    </template>
  </v-data-table>
</template>

<script>
export default {
  data () {
    return {
      // In reality this gets filled from a db:
      items: [
        { id: 1, type: 'abc' },
        { id: 2, type: 'abcd' },
        { id: 3, type: 'efg' },
      ]
    }
  },
  methods: {
    typeImageSource: function (type) {
      let src = ''
      try {
        src = require(`@/assets/types/${('' + type).toLowerCase()}.png`)
      } catch (error) {
        console.warn(`Image for type ${type} could not be found! Please add "${('' + type).toLowerCase()}.png" to the folder "@/assets/types/".\n\n`, error)
        return null
      }
      return src
    },
  },
}
</script>

Comments

0

If you are using nuxt use <img :src="'_nuxt/path_to_your_local_image'" />

if you are using vue first use static src import : <img src="path_to_your_local_image" />

then inspect image element to see what src is rendered to the browser then replace it with a dynamic src

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.