Objective
I want to pass the path of an image as a prop to a component. I want the component to use the prop to dynamically generate the background image.
All my images in an assets folder in the Vue src folder. The path looks like '@/assets/images/subject/computers.jpeg'
Problem
No background image appears
This is what renders on the page:
However, nothing shows up
Strange Behaviour
For some reason, adding the exact same path name '@/assets/images/subject/computers.jpeg' in CSS works (Adding it in the <style> tags). It just doesn't work if it's v-bind inline style.
Here is what it looks like in my CSS
The problem with this though, is that it is not dynamically rendered CSS.
I inspected the element further and noticed some strange behavior. As you can see, the inline style is reading the image path as '@/assets/images/subject/computers.jpeg' (element.style in image below).
Whereas adding the path in CSS, changes '@/assets/images/subject/computers.jpeg' to 'http://localhost:8080/img/computers.7f3748eb.jpeg', which then correctly renders the background image.
Question
I suppose my question is twofold:
- How would you dynamically render a background image in Vue with props? Or is there a better way to do this?
- Why does binding inline styles not resolve the path (keeps using '@'), while adding it directly in the <script> tags does resolve the path?
Solution
Okay, big thank you to tao & Bernard Borg for helping me wrap my head around this.
I was able to solve this using computed properties like so:
const imgSrc = computed(() => require(`@/assets/images/subject/${props.subject.image}`))
Because of the way VueLoader (which is default in Vue) resolves the paths, I couldn't store the '@' path in the prop itself. Instead, the prop is just the image/file name (ex. "computers.jpeg"), and the computed property with require() handles resolving the prepended path to the image.
Afterwards, I added the computed property to my binded inline style like so:
<div v-bind:style="{ backgroundImage: `url('${imgSrc}')` }">
Voila! It finally works.
TLDR
Pass only the image/file name as a prop, and prepend the path using require() in a computed property.
Cheers