admin管理员组文章数量:1398828
I need to load around 1000 static images, .gifs, and videos for an online slideshow presentation. Currently all items are loading at once and viewers need to wait to see the first item. How to load each item after the one before is finished loading?
Vue.js Vuetify.js code:
<v-row v-for="(objkts, index) in group" :key="index">
<v-col v-for="objkt in objkts" :key="objkt.id">
<v-card :key="index" width="100vh">
<v-img
max-width="100vh"
:src="img(objkt)"
></v-img>
</v-card>
</v-col>
</v-row>
I need to load around 1000 static images, .gifs, and videos for an online slideshow presentation. Currently all items are loading at once and viewers need to wait to see the first item. How to load each item after the one before is finished loading?
Vue.js Vuetify.js code:
<v-row v-for="(objkts, index) in group" :key="index">
<v-col v-for="objkt in objkts" :key="objkt.id">
<v-card :key="index" width="100vh">
<v-img
max-width="100vh"
:src="img(objkt)"
></v-img>
</v-card>
</v-col>
</v-row>
Share
Improve this question
asked Oct 21, 2021 at 7:40
TomTom
6,03421 gold badges85 silver badges134 bronze badges
4 Answers
Reset to default 4Solution:
Using an image list you need to dynamically set the src property on each image only when the previous image is loaded
Steps (5):
- Create an array of image data with image URL stored in asrc property(you can name it anything).
- Render each image from list using v-for directive.
- Set image src to image.src instead of asrc
<img v-for="(image,index) in group" :key="index" :src="image.src"
- Also set an image load event to call loading of next image
<img v-for="(image,index) in group" :key="index" :src="image.src" @load="loadNextimage(index)"/>
- Whenever image loader is called then add src property to the image. This will start the image to load.
loadNextimage(currentIndex){ let nextIndex = currentIndex+1 if( nextIndex < this.group.length){ let img = this.group[nextIndex] img.src = img.asrc delete img.asrc Vue.set(this.group, nextIndex, img) } }
new Vue({
el: '#app',
data(){
return {
group: [
{ id: 1, title: '', asrc: 'https://source.unsplash./collection/190727/120x120'},
{ id: 2, title: '', asrc: 'https://source.unsplash./collection/8961198/120x120'},
{ id: 3, title: '', asrc: 'https://source.unsplash./collection/190723/120x120'},
{ id: 4, title: '', asrc: 'https://source.unsplash./collection/KizanWcExgU/120x120'}
]
}
},
mounted(){
this.loadNextimage(-1)
},
methods:{
loadNextimage(currentIndex){
let nextIndex = currentIndex+1
if(nextIndex<this.group.length){
let img = this.group[nextIndex]
img.src = img.asrc
delete img.asrc
Vue.set(this.group,nextIndex,img)
}
}
}
});
img {
height: 120px;
width:120px;
}
img:not([src]){
background: url(https://www.slntechnologies./wp-content/uploads/2017/08/ef3-placeholder-image.jpg);
background-size:cover;
}
<script src="https://cdnjs.cloudflare./ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr/npm/[email protected]/dist/vuetify.js"></script>
<div id="app">
<img
v-for="(image,index) in group" :key="index"
:src="image.src"
@load="loadNextimage(index)"
>
</div>
This is similar to Alphesh's solution but I think it's a little bit easier to read. The idea is to set up a simple queueing system with three properties:
- imagesToLoad - The list of images/videos you need to load
- loadingImage - The image that is currently loading
- loadedImages - The images that have already loaded
You'll also have a simple method called queueNextImage
which should be called by the mounted
hook (to start the first image loading) and then again when an image is finished loading that looks like this:
queueNextImage() {
if(this.loadingImage !== null) {
this.loadedImages.push(this.loadingImage)
}
this.loadingImage = this.imagesToLoad.shift()
}
When you start imagesToLoad
will be populated with all the image URLs you'd like to load and loadedImages
will be an empty array.
The template will iterate through the loadedImages
rendering them in a regular loop and will have a single img
element having the src
attribute bound to the value of loadingImage
and which fires the queueNextImage
from the onLoad
event of the image.
Full example:
<template>
<div>
<p>
Images to load: <span>{{imagesToLoad.length}}</span>
Loading image: <span>{{loadingImage}}</span>
Images Loaded: <span>{{loadedImages.length}}</span>
</p>
<img v-for="item in loadedImages" v-bind:key="item" v-bind:src="item" />
<img v-on:load="queueNextImage" v-bind:src="loadingImage" />
</div>
</template>
<script>
export default {
mounted: function() {
this.queueNextImage();
},
methods: {
queueNextImage() {
if(this.loadingImage !== null) {
this.loadedImages.push(this.loadingImage)
}
this.loadingImage = this.imagesToLoad.shift()
},
},
data: () => ({
loadedImages: [],
loadingImage: null,
imagesToLoad: Array.from({length:200},(v,k)=>`https://via.placeholder./${k+850}`),
}),
};
</script>
Try it on CodeSandbox.
You can use lazy
ponent from vuetify: https://vuetifyjs./en/ponents/lazy/
Wrap your code inside this ponent and your html will be loaded based on visibility.
As far as I understand you want something like loading images one by one in the ascending order of the index.
You can try one approach like:
- Creating an
async
method andawait
the loading of the images in loop.
Pseudocode Example:
- First replace the code in vue template
<v-img
max-width="100vh"
:src="imgCollection[index]"
></v-img>
- Then load the images asynchronously one by one.
async function loadImages() {
imagesList.forEach((img, index) => {
var data = await getImageData(img.url);
// update the data into your array
imgCollection[index] = data;
});
}
本文标签: javascriptLoad each item after the one before is finished loading in Vue JSStack Overflow
版权声明:本文标题:javascript - Load each item after the one before is finished loading in Vue JS - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744644207a2617301.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论