-1👍
I don’t think I was clear enough with my comments, so I’ll explain what I meant with an example; you should be able to apply this to your use case with minimal effort. My src file structure and a screenshot of the result are also at the bottom of this answer.
The template I’ve made is basically the same as yours (without the extra divs with classes):
<template>
<div>
<div v-for="image in images" :key="image">
<img :src="selectImage(image)" :alt="image" />
</div>
</div>
</template>
Here’s my script. I’ll go through it all below:
<script>
export default {
name: 'app',
computed: {
images: function() {
const x = require.context('@/assets/card-images/', true, /\.png$/)
return this.importAll(x)
}
},
methods: {
importAll(r) {
return r.keys().map(x =>
x.substring(2, x.length) // remove "./" from file names
)
},
selectImage(image) {
return require('@/assets/card-images/' + image)
}
}
}
</script>
computed
The computed
section is where you define your dynamically generated or computed values. Since you want your images to be dynamically generated, I’ve made images
a computed function (can probably just be a value, you can play around with that).
All that images
does is it uses require.context
to get a list of all of the .png
images in my @/assets/card-images/
folder, and trims the first couple of characters from them.
methods
importAll
just retrieves and trims the image names. I’ve done this because otherwise, it’ll think the images are at @/assets/card-images/./xxxxx.png
– there’s probably a better way of doing this but it works well enough.
selectImage
gets an image from the file name you pass in (if it exists). If the image name doesn’t exist, this will break but that shouldn’t happen with how this is implemented.
Note: You can technically shorten the v-for loop by putting it directly on the img tag if you really want to, though I’d argue this is less readable:
<template>
<div>
<img v-for="image in images"
:key="image"
:src="selectImage(image)"
:alt="image" />
</div>
</template>
Here is my src
folder structure. It doesn’t matter what the images are called, as long as they have the same extension as you’re using in your script tag:
Here is what the code prints out (all of the images are just copies of the Vue logo):
EDIT
If you want to keep your initial images
array, you can move the computed
stuff into the lifecycle method mounted
or created
(depending on your use-case). Read more about lifecycle methods here or here. Here’s what my component would look like with the calculations in mounted
:
<template>
<div>
<div v-for="image in images" :key="image">
<img :src="selectImage(image)" :alt="image" />
</div>
</div>
</template>
<script>
export default {
name: 'app',
data() {
return {
images: []
}
},
mounted() {
const x = require.context('@/assets/card-images/', true, /\.png$/)
this.images = this.importAll(x)
},
methods: {
importAll(r) {
return r.keys().map(x =>
x.substring(2, x.length) // remove "./" from file names
)
},
selectImage(image) {
return require('@/assets/card-images/' + image)
}
}
}
</script>
-1👍
Use a requireAll
method to get an array, and your count. Or a custom loader
.
How to load all files in a directory using webpack without require statements