How to import and use image in a Vue single file component? - vue.js

I think this should be simple, but I am facing some trouble on how to import and use an image in Vue single file component. Can someone help me how to do this? Here is my code snippet:
<template lang="html">
<img src="zapierLogo" />
</template>
<script>
import zapierLogo from 'images/zapier_logo.svg'
export default {
}
</script>
<style lang="css">
</style>
I have tried using :src, src="{{ zapierLogo }}", etc. But nothing seems to work. I was not able to find any example too. Any help?

As simple as:
<template>
<div id="app">
<img src="./assets/logo.png">
</div>
</template>
<script>
export default {
}
</script>
<style lang="css">
</style>
Taken from the project generated by vue cli.
If you want to use your image as a module, do not forget to bind data to your Vuejs component:
<template>
<div id="app">
<img :src="image"/>
</div>
</template>
<script>
import image from "./assets/logo.png"
export default {
data: function () {
return {
image: image
}
}
}
</script>
<style lang="css">
</style>
And a shorter version:
<template>
<div id="app">
<img :src="require('./assets/logo.png')"/>
</div>
</template>
<script>
export default {
}
</script>
<style lang="css">
</style>

It is heavily suggested to make use of webpack when importing pictures from assets and in general for optimisation and pathing purposes
If you wish to load them by webpack you can simply use :src='require('path/to/file')' Make sure you use : otherwise it won't execute the require statement as Javascript.
In typescript you can do almost the exact same operation: :src="require('#/assets/image.png')"
Why the following is generally considered bad practice:
<template>
<div id="app">
<img src="./assets/logo.png">
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss">
</style>
When building using the Vue cli, webpack is not able to ensure that the assets file will maintain a structure that follows the relative importing. This is due to webpack trying to optimize and chunk items appearing inside of the assets folder. If you wish to use a relative import you should do so from within the static folder and use: <img src="./static/logo.png">

I came across this issue recently, and i'm using Typescript.
If you're using Typescript like I am, then you need to import assets like so:
<img src="#/assets/images/logo.png" alt="">

You can also use the root shortcut like so
<template>
<div class="container">
<h1>Recipes</h1>
<img src="#/assets/burger.jpg" />
</div>
</template>
Although this was Nuxt, it should be same with Vue CLI.

These both work for me in JavaScript and TypeScript
<img src="#/assets/images/logo.png" alt="">
or
<img src="./assets/images/logo.png" alt="">

..when everything else fails, like in my case as i tried to import a placeholder i used several times in a multipaged Vuelectro-app - but this time inside a sub-subcomponent where none of the suggested solutions worked (as they usually do)..
<template>
<div id="app">
<img :src="image"/>
</div>
</template>
<script>
export default {
data() { return {image: null, ...} },
methods: {
solveImage(){
const path = require('path')
return path.join(process.cwd(), '/src/assets/img/me.jpg')
},
...
},
mounted: {
this.image = this.solveImage()
...
}
}
</script>
..should do it.
if it even works better in created-lifecycle-hook or you'd prefer to require path globally and just call
this.image = path.join(...)
in one of the hooks - you should test yourself.

I encounter a problem in quasar which is a mobile framework based vue, the tidle syntax ~assets/cover.jpg works in normal component, but not in my dynamic defined component, that is defined by
let c=Vue.component('compName',{...})
finally this work:
computed: {
coverUri() {
return require('../assets/cover.jpg');
}
}
<q-img class="coverImg" :src="coverUri" :height="uiBook.coverHeight" spinner-color="white"/>
according to the explain at https://quasar.dev/quasar-cli/handling-assets
In *.vue components, all your templates and CSS are parsed by vue-html-loader and css-loader to look for asset URLs. For example, in <img src="./logo.png"> and background: url(./logo.png), "./logo.png" is a relative asset path and will be resolved by Webpack as a module dependency.

For Vue 3 I had to use
<template>
<div id="app">
<img :src="zapierLogo" />
</div>
</template>
<script>
import zapierLogo from 'images/zapier_logo.svg'
export default {
...
data: function () {
return {
zapierLogo
}
}
}
</script>
Both src="#/assets/burger.jpg" and src="../assets/burger.jpg" didn't seem to work.

I'm also facing same problem to display the assets image. Finally this two way work fine for me-
<img src="#/assets/img/bg1.png" />
and
<img :src="require('#/assets/img/bg1.png')" />

in my case i have a base64 image and have to import for parse the mimeType and data from the image
this how the template look like
<template>
<img
#click="openCardDetail(item)"
class="thumbnailInfo"
width="80"
height="50"
:src="getImageToShow(item.stationeryThumbnail)"
/>
</template>
Here i imported the image
import image from '#/assets/noimage.png'
then i instantiated it
data: () => ({
...
image: image,
})
then i used only if there is no data in the item
getImageToShow(item) {
if(item != null && item?.mimeType !== '' && item?.base64ImageData !== '') {
return `data:${item?.mimeType};base64,${item.base64ImageData};`
}
return `${this.image}`;
}
it solved my problem

Related

How to make text interpolation work inside css functions and router links

I was trying to implement a reusable card component, so I printed them out inside variable properties that is changed image by image
This is my code. As for title, it works perfectly. I implemented it many times, so my issue is different. I also added this props' text inside mustaches, so I can change link and image out of my card, but it doesn't work, so I need your help. I might just not understand how text interpolation works. But I think that vue supports the way to create reusable cards within a component
<template>
<RouterLink class="card" to="{{ link }}">
<div class="card__background" style="background-image: url({{ image }})"></div>
<div class="card__content">
<h3 class="card__heading">{{ title }}</h3>
</div>
</RouterLink>
</template>
<script>
import { RouterLink } from 'vue-router';
export default {
props: ['link', 'image', 'title'],
created() {
console.log(this.link)
console.log(this.image)
console.log(this.title)
},
}
</script>
I think you need to use the v-bind directive. This directive allows you to bind the value of an HTML attribute to a dynamic expression.
Here's how you can modify your code to use the v-bind directive:
<template>
<RouterLink class="card" v-bind:to="link">
<div class="card__background" v-bind:style="{ backgroundImage: `url(${image})`
}"></div>
<div class="card__content">
<h3 class="card__heading">{{ title }}</h3>
</div>
</RouterLink>
</template>
<script>
import { RouterLink } from 'vue-router';
export default {
props: ['link', 'image', 'title'],
created() {
console.log(this.link)
console.log(this.image)
console.log(this.title)
}
}
</script>

Vue.js Issue: Prop doesn't change image v-bind:src

I've been trying to pass a prop to a component, which is a URL to an image for Section component to update v-bind:src of dom img tag, but somehow the image does not show up.
I can't see what's wrong.
File: App.vue
<template>
<div id="app">
<Section img="../assets/linux.png" />
</div>
</template>
<script>
import Section from "./components/Section.vue";
export default {
name: "app",
components: {
Section
}
};
</script>
File: Section.vue
<template>
<div>
<img :src="img" />
</div>
</template>
<script>
export default {
props: {
img: String
}
};
</script>
I suspect that the issue is due to the relative path you are using. I assume that ../assets/linux.png resolves to the right image URL with respect to App.vue, but it actually needs to resolve to the right image with respect to your <Section> component.
Based on what I can tell from the code you've shared, It seems like you can solve this by updating App.vue as follows:
<template>
<div id="app">
<Section img="../../assets/linux.png" />
</div>
</template>
...
I should, however, point out that you are getting absolutely no benefit from passing the image source as a prop like this. Since it is not bound to a reactive data property in App.vue, you may as well just omit that prop altogether.

Using Nuxt.js alias in component attributes

I have a collection of images, audios and videos that should be displayed by a component one by one. All media is placed in assets sub-directories.
Given a simple Vue component for images like:
<template>
<img :src="src" :alt="src"></a>
</template>
<script>
export default {
name: "ImgDisplay",
props: ['src']
}
</script>
if I try to use it on some page:
<template>
<ImgDisplay src="~/assets/test.png"/>
</template>
the image is not actually displayed.
Vue component for MP3-files looks like this:
<template>
<vue-plyr>
<audio controls>
<source :src="src" type="audio/mp3"/>
</audio>
</vue-plyr>
</template>
<script>
export default {
name: "PlyrAudio",
props: ['src']
}
</script>
Then in document I have:
<template>
<div>
<article class="infobox">
<h6>Recording 1</h6>
<PlyrAudio src="~/assets/media/recording-1.mp3"/>
</article>
<article class="infobox">
<h6>Recording 2</h6>
<PlyrAudio src="~/assets/media/recording-2.mp3"/>
</article>
</div>
</template>
<script>
import PlyrAudio from "../components/media/PlyrAudio";
export default {
name: "PlyrAudioTest",
components: {PlyrAudio}
}
</script>
which does not work either, PlyrAudio component does not seem to find referenced mp3 files.
How can one use Nuxt.js aliases (~, ~~, #, ##) in component attributes? Is there some dedicated function to resolve ~ in <script> section of ImgDisplay and PlyrAudio or am I missing something?

Vue: binding img src doesn't work but hardcoding it works

When Im binding my image source it can't find the image
<template>
<div class="card">
<img class="card-img-top" :src="this.offer.resource">
<div class="card-body text-center">
<h1>{{offer.name}}</h1>
<p>{{offer.description}}</p>
<h2>{{offer.price}}€</h2>
</div>
</div>
</template>
<script>
import Offer from '#/models/Offer.js'
export default {
props: { offer: Offer},
created: function() {
console.log(this.offer.resource);
}
}
</script>
I get the error: offer_pizza.jpg:1 GET http://localhost:3000/#/assets/images/offer_pizza.jpg 404 (Not Found)
the console.logprints out the correct path: #/assets/images/offer_pizza.jpg
Howerever when I just hardcode it like this:
<img class="card-img-top" src="#/assets/images/offer_pizza.jpg" >
it works fine.
If you want to use it the way you did, your offer object would have to look like this:
offer: {
...
resource: require('#/assets/images/offer_pizza.jpg')
}
Your current offer probably has a string there.

How can I solve "Interpolation inside attributes has been removed. Use v-bind or the colon shorthand"? Vue.js 2

My Vue.js component is like this:
<template>
<div>
<div class="panel-group" v-for="item in list">
...
<div class="panel-body">
<a role="button" data-toggle="collapse" href="#purchase-{{ item.id }}" class="pull-right" aria-expanded="false" aria-controls="collapseOne">
Show
</a>
</div>
<div id="purchase-{{ item.id }}" class="table-responsive panel-collapse collapse" role="tabpanel">
...
</div>
</div>
</div>
</template>
<script>
export default {
...
computed: {
list: function() {
return this.$store.state.transaction.list
},
...
}
}
</script>
When executed, there exists an error like this:
Vue template syntax error:
id="purchase-{{ item.id }}": Interpolation inside attributes has
been removed. Use v-bind or the colon shorthand instead.
How can I solve it?
Use JavaScript code inside v-bind (or shortcut ":"):
:href="'#purchase-' + item.id"
and
:id="'purchase-' + item.id"
Or if using ES6 or later:
:id="`purchase-${item.id}`"
Use v-bind or shortcut syntax ':' to bind the attribute.
Example:
<input v-bind:placeholder="title">
<input :placeholder="title">
Just use
:src="`img/profile/${item.photo}`"
If you're pulling data from an array of objects, you need to include require('assets/path/image.jpeg') in your object like I did below.
Working example:
people: [
{
name: "Name",
description: "Your Description.",
closeup: require("../assets/something/absolute-black/image.jpeg"),
},
Using require(objectName.propName.urlPath) in the v-img element did not work for me.
<v-img :src="require(people.closeup.urlPath)"></v-img>
The easiest way is too require the file address:
<img v-bind:src="require('../image-address/' + image_name)" />
The complete example below shows ../assets/logo.png:
<template>
<img v-bind:src="require('../assets/' + img)" />
</template>
<script>
export default {
name: "component_name",
data: function() {
return {
img: "logo.png"
};
}
};
</script>
The most elegant solution is save images outside Webpack. By default, Webpack compress images in Base64, so if you save images in your assets folder, that doesn't work because Webpack will compress images in base64, and that isn’t a reactive variable.
To solve your problem, you need to save your images in your public path. Usually the public path is in "public" folder or "statics".
Finally, you can do this:
data(){
return {
image: 1,
publicPath: process.env.BASE_URL
}
}
And your HTML you can do this:
<img :src="publicPath+'../statics/img/p'+image+'.png'" alt="HANGOUT PHOTO">
When to use the public folder
You need a file with a specific name in the build output
File depends on a reactive variable that can change in execution time
You have images and need to dynamically reference their paths
Some library may be incompatible with Webpack and you have no other option but to include it as a <script> tag.
More information: "HTML and Static Assets" in Vue.js documentation