How do I lazy load item lists on Vuejs and Vuetify's lazyload?

11,616

Solution 1

There is a new virtual-scroller component, but it doesn't work with responsive content like grid rows/cols. Instead use v-lazy...

I discovered that the columns need to have defined min-height (approx. to the expected height of the cards) in order for the v-lazy intersection observer to work. Use something like a v-sheet or v-responsive to set the min-height and contain the cards.

Also bind the v-model of the v-lazy to each post (ie: post.isActive), instead of a global isActive var...

        <v-col lg="3" md="4" sm="6" cols="12" v-for="(post, index) in posts">
                <v-sheet min-height="250" class="fill-height" color="transparent">
                    <v-lazy 
                        v-model="post.isActive" :options="{
                            threshold: .5
                        }"
                        class="fill-height">
                        <v-card class="fill-height" hover>
                            <v-card-text>
                                <v-row :key="index" @click="">
                                    <v-col sm="10" cols="12" class="text-sm-left text-center">
                                        #{{ (index+1) }}
                                        <h2 v-html="post.title"></h2>
                                        <div v-html="post.body"></div>
                                    </v-col>
                                </v-row>
                            </v-card-text>
                        </v-card>
                    </v-lazy>
                </v-sheet>
        </v-col>

   

Demo: https://codeply.com/p/eOZKk873AJ

Solution 2

I can suggest another solution with v-intersect, which works perfect for me.

Sorry, the snippet may be not working as composed of my code, but the idea should be pretty clear

<template>
  <v-list class="overflow-y-auto" max-height="500">
    <v-list-item v-for="item in items">
      {{ item.name }}
    </v-list-item>
    <v-skeleton-loader v-if="moreDataToAvailable" v-intersect="loadNextPage" type="list-item@5" />
  </v-list>
</template>

<script lang="ts">
import Vue from 'vue'

const pageSize = 10

export default Vue.extend({
  data(): any {
    return {
      pageLoaded: 0,
      totalCount: 100,//fetch from API
      items: []
    }
  },
  computed: {
    moreDataToAvailable (): boolean {
      return Math.ceil(this.totalCount / pageSize) - 1 > this.pageLoaded
    }
  },
  methods {
    async loadNextPage (entries: IntersectionObserverEntry[]) {
      if (entries[0].isIntersecting && this.moreDataToAvailable) {
        const nextPage = this.pageLoaded + 1
        const loaded = await this.loadPage(nextPage) //API call
        loaded.data.forEach((item: any) => this.items.push(item))
        this.totalCount = loaded.totalCount
        this.pageLoaded = nextPage
      }
    },
  }
})
</script>
Share:
11,616

Related videos on Youtube

Pruthvi Shetty
Author by

Pruthvi Shetty

Updated on June 04, 2022

Comments

  • Pruthvi Shetty
    Pruthvi Shetty over 1 year

    Im trying to make an infinite scroll list but it's really not lazy loading, been stuck with this for hours, the whole list will come in.

          .....
        <v-col
          v-for="(post, i) in posts"
          :key="i"
          cols="12"
        >
        <v-lazy
        v-model="isActive"
        :options="{
          threshold: .5
        }"
        transition="fade-transition"
      >
              {{Content here}}
         </....
    

    API used for test : https://jsonplaceholder.typicode.com/posts

    • AlekseyHoffman
      AlekseyHoffman over 3 years
      If you can update Vuetify to 2.3.0-beta.3, it has a virtual-scrollers component that you could use. Here's documentation for it
    • Zim
      Zim almost 3 years
      but the problem is that virtual-scroller doesn't work with grid rows/cols ... it only works with a single "column" of content
  • Pruthvi Shetty
    Pruthvi Shetty over 3 years
    this worked so nicely!!! thank you soo much! complex stuff like this is really impossible to understand using the documentation itself. I had been struggling with this for 3 days now, Appreciate the help! :D
  • George Marios
    George Marios over 2 years
    This is the correct way of fetching more items on intersect, in contrast to the accepted answer that lazy loads items that are already fetched. I would suggest concating the old and new arrays instead of pushing each item in a loop, but still works.
  • sickfar
    sickfar over 2 years
    I’m doing this way now: this.items.push[…loaded]