In Vue JS, ensure that each item is loaded only after the previous item has finished loading

Is there a way to optimize the loading of around 1000 static images, .gifs, and videos for an online slideshow presentation? Currently, all items are loading simultaneously causing viewers to wait to see the first item. How can each item be loaded after the one before it is finished loading?

Below is an example of Vue.js Vuetify.js code that may help achieve this:

<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>

Answer №1

Resolution:

To accomplish this task, utilize an image list and dynamically assign the src property to each image only after the previous image has finished loading.

Steps (5):

  1. Generate an array containing image data with the image URL stored in the asrc property (this can be named anything).
  2. Display each image from the list using the v-for directive.
  3. Assign the image src to image.src instead of asrc.
<img 
  v-for="(image,index) in group" :key="index"
  :src="image.src"
  1. Include an image load event to trigger the loading of the next image.
<img 
  v-for="(image,index) in group" :key="index"
  :src="image.src"
  @load="loadNextImage(index)"/>
  1. When the image loader is activated, add the src property to the image, initiating the image loading process.
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.com/collection/190727/120x120'},
          { id: 2, title: '', asrc: 'https://source.unsplash.com/collection/8961198/120x120'},
          { id: 3, title: '', asrc: 'https://source.unsplash.com/collection/190723/120x120'},
          { id: 4, title: '', asrc: 'https://source.unsplash.com/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.com/wp-content/uploads/2017/08/ef3-placeholder-image.jpg);
  background-size:cover;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="90e6e5f5e4f9f6e9d0a2bee8">[email protected]</a>/dist/vuetify.js"></script>

<div id="app">
    <img 
      v-for="(image,index) in group" :key="index"
      :src="image.src"
      @load="loadNextImage(index)"
    >
</div>

Answer №2

My approach bears a resemblance to Alphesh's solution, although I believe it offers improved readability. The concept involves establishing a straightforward queue system with three key properties:

  1. imagesToLoad - Represents the list of images/videos that need loading
  2. loadingImage - signifies the image currently being loaded
  3. loadedImages - indicates the images that have already been loaded

In addition to these properties, you will implement a simple method called queueNextImage, which should be invoked by the mounted hook (to initiate the loading of the initial image) and again once an image has finished loading. This method is structured as follows:

queueNextImage() {
  if(this.loadingImage !== null) {
    this.loadedImages.push(this.loadingImage)
  }
  this.loadingImage = this.imagesToLoad.shift()
}

At the outset, imagesToLoad will contain all the URLs of the images you intend to load, while loadedImages will be an empty array.

The template will iterate over the loadedImages, displaying them in a standard loop, and include a single img element where the src attribute is bound to the value of loadingImage. This element triggers the queueNextImage function upon the onLoad event of the image.

For a comprehensive 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.com/${k+850}`),
  }),
};
</script>

Experiment with this on CodeSandbox.

Answer №3

For a convenient way to lazy load content in your Vue project, consider using the lazy component available in Vuetify. Simply wrap your code within this component and watch as your HTML is loaded based on visibility.

Answer №4

So, if I understand correctly, you are looking for a way to load images one by one in the order of their index.

One possible solution could be:

  • Implementing an asynchronous method and using await to load each image in a loop.

To illustrate, here's an example in pseudocode:

  1. Begin by updating the code in your vue template.
<v-img
    max-width="100vh"
    :src="imgCollection[index]"
></v-img>
  1. Then proceed to asynchronously load the images one by one.
async function loadImage() {
    imagesList.forEach(async (image, index) => {
        var imageData = await getImageData(image.url);
        
        // Update the data in your array accordingly
        imgCollection[index] = imageData;
    });
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to activate a function in a sibling component without using Prop Drilling?

Looking at the image, you can see the structure of components I have. <Invoice> <Left></Left> <Right></Right> </Invoice> In the Left component, there is a form, and in the Right component, there is a Submit button l ...

Adding a new property to a reactive object in VueJS 3: A simple guide

export default { setup() { const imageUrl = ref(""); const title = ref(""); const description = ref(""); var source = "Global"; const form = reactive({ title: "", descript ...

The paragraph text should dynamically update upon clicking a button based on JavaScript code, however, the text remains unchanged despite attempts to modify it

I recently started learning JavaScript and wanted to update the content of a paragraph when a button is clicked. However, I encountered an issue where this functionality doesn't seem to work. <body> <p id="paragraph">Change Text on cl ...

A step-by-step guide on accessing and displaying local Storage JSON data in the index.html file of an Angular project, showcasing it on the

I am facing an issue with reading JSON data from localStorage in my Angular index.html file and displaying it when viewing the page source. Below is the code I have attempted: Please note that when checking the View page source, only plain HTML is being ...

Use JavaScript to convert only the initial letter to uppercase

Once again, I am in the process of learning! Apologies for the simple questions, but learning is key... Attempting to implement a trick I found online to change all letters to uppercase, I am now trying to adjust it to only capitalize the first letters. T ...

Restrict the selection of dates in the jQuery UI datepicker by disabling public holidays, weekends, the next day after 10am, and only allowing Tuesday, Wednesday, and Thursday as

I found a code snippet on disabling weekends, public holidays, and the next day after 10 am using JQuery UI Datepicker. However, I'm facing an issue where I want to restrict selections to only Tuesday, Wednesday, and Thursday. // JavaScript logic for ...

Prop validation error: The property "title" must be a string with a value of **, but a number with a value of ** was provided

My Vue js code displays data from a JSON API in a modal. The issue is that the title should be dynamic, but it only works when clicked twice. On the first click, I get an error and the cancel button, which triggers the hidemodal() function, crashes. Can an ...

Javascript's ReferenceError occasionally acts inconsistently when using Firefox's scratchpad

While delving into the world of Javascript for learning purposes, I encountered an unexpected behavior. Let's explore this scenario: function hello(name) { let greet = 'Hello ' alert(greet + name) } hello('world') alert(gree ...

What is the best way to enable autocomplete in AngularJS?

I am working with an object that contains both a name and an ID. I want to implement autocomplete functionality based on the name property. Below is the code snippet that I have tried: //Js file var app=angular.module("myapp",[]); app.controller("controll ...

Error code E11000 is indicating that a duplicate key issue has occurred in the collection "blog-api.blogs" where the index "id_1" is

Issue with Error E11000 duplicate key error collection: blog-api.blogs index: id_1 dup key: { id: null } Encountering an error when trying to insert data after initially inserting one successfully. Referencing the blogSchema.js: const mongoose = req ...

Tips for enhancing the functionality of components within Vue

My expertise lies primarily in React, and I'm now exploring the Vue-centric approach to achieve the following: I want to enhance this component: , so that the label-position is set to top on mobile devices and left on desktop. However, I'm not s ...

Redux - Preventing Overwriting of Product Quantity in Cart by Creating a New Object

Is there a way to address the issue where adding the same product multiple times to the cart creates new objects instead of increasing the quantity? switch (action.type) { case actionTypes.ADD_TO_CART: const product = state.products.find((p) = ...

Scrolling up or down in an HTML webpage using a script

Seeking a code snippet for my website that will allow me to achieve the following functionality: Upon clicking on text_head1, a list of lines should scroll down. Subsequently, when I click on text_head2, the previous list should scroll up while the new l ...

Obtaining page information from a frame script in e10s-enabled Firefox: A guide

One of the challenges I'm facing is with my Firefox extension, where a function loads page information using the following code: var title = content.document.title; var url = content.document.location.href; However, with the implementation of multi- ...

How can I adjust the font size of material-ui buttons while ensuring that they scale appropriately?

Having trouble adjusting the font sizes on Material-UI's RaisedButton for React and ensuring that the button scales properly along with it. <RaisedButton label={<span className="buttonText">Log in Here</span>} /> CSS: .buttonText ...

Discovering checkboxes in HTML using jQuery

Greetings! I have limited knowledge when it comes to using jQuery. I am currently facing an issue with the Checkbox attribute. Below, you will find the code snippet that I have mentioned: Code: $( this ).html() Output: <input name="cb_kot[]" class= ...

Node.js (npm) is still unable to locate python despite setting %PYTHON% beforehand

Trying to get Node.js to work is proving to be more challenging than expected! Despite having two versions of Python on my computer, it seems that Node.js only works with the older version, 2.7. When I encountered an error, it prompted me to set the path ...

What is the best way to assign a unique color to each circle?

Struggling to assign random colors to each circle in my canvas. Currently, they all have the same color that changes upon refresh. I'm aiming for unique colors on each circle but my attempts have been unsuccessful so far. Check out my code below: v ...

Utilizing Typescript with Vue 3's Injection Feature

Using the new Vue 3 Composition API, I have created a "store" for reactive data. const state = reactive<State>({ accessToken: undefined, user: undefined, }); export default { state: readonly(state), } When my app is created, I pass the store ...

The JS variable text consistently displays as undefined

I have come across multiple posts on this topic, but none of them seem to be getting through to me or they are slightly different. This issue has been causing me confusion for quite some time. Despite my efforts to find a solution, I am met with conflicti ...