Reputation: 35
How to render images, if i get path from json file. Default i use require('../assets/img/item-image.png')
. But i have no idea, how use it in this case
Component:
<div v-for="(item, index) in items">
<img :src="item.src">
</div>
<script>
import axios from 'axios'
export default {
name: 'componentName',
data () {
return {
items: null
}
},
mounted () {
axios
.get('./test.json')
.then(response => (this.items = response.data))
}
}
</script>
JSON file:
[
{
"id": 1,
"title": "item title",
"src": "../assets/img/item-image.png",
"alt": "item-image",
"text": "item body"
}
]
Upvotes: 1
Views: 1877
Reputation: 739
This was how I solved it. I kept getting an error when using the regex above to add require
to the src attribute in the json. This is what I did instead and it worked for me.
I am using fetch()
to read the json which I am watching with json-server
. The json is basically an array (cokeImages) of objects when you use res.json()
to convert it.
{
"cokeImages": [
{
"title": "Cocacola Life",
"description": "Lorem ipsum no sicut anon in aquila no ager. In homines ad majorem tempus avis, et cum in pecunia imoten tua",
"src": "../assets/cocacola-cans/cocacola-life.png",
"id": 1,
"name": "cocacola-life",
"nutrition": [
{ "title": "sodium", "value": "150 cl", "percent": "25%" },
{ "title": "Total Fats", "value": "0g", "percent" : "0%" },
{ "title": "sodium (mg)", "value": "40mg", "percent": "0%"},
{ "title": "potasium", "value": "4g", "percent": "0%" },
{ "title": "calcium", "value": "0g", "percent": "0%"}
]
},
{
"title": "Cocacola Zero",
"description": "Lorem ipsum no sicut anon in aquila no ager. In homines ad majorem tempus avis, et cum in pecunia imoten tua",
"src": "../assets/cocacola-cans/cocacola-zero.png",
"id": 2,
"name": "cocacola-zero",
... (and so on)...
as you can see, the name property in each object is also the name I used in each images src
.
It is that name property I used in the map()
method to attach require
to each src.
mounted(){
fetch("http://localhost:3000/cokeImages")
.then(response => response.json())
.then(arrayOfOjects => {
console.log(arrayOfObjects)
this.cokeImages = data.map(eachObject => {
return {...eachObject, src: require(`../assets/cocacola-cans/${eachObject.name}.png`)}
})
console.log(this.cokeImages)
})
.catch(err => {
console.log(err.message)
})
}
Upvotes: -1
Reputation: 164910
You need to keep using require()
in order to let Webpack know to include your images when bundling.
Because Webpack bundles at compile time and your images are only known at runtime, this is best done by keeping part of the path static so Webpack can optimistically include the right files.
For example, if all your images are under ../assets/img
, the best option would look like this
async mounted () {
const pathRegex = /^\.\.\/assets\/img\//
const { data } = await axios.get("./test.json")
this.items = data.map(item => ({
...item,
src: require(`../assets/img/${item.src.replace(pathRegex, "")}`)
}))
}
Webpack will then bundle every file under ../assets/img
and at runtime, will be able to resolve the paths you supply.
See https://webpack.js.org/guides/dependency-management/#require-with-expression
Upvotes: 2