How do I lazy load item lists on Vuejs and Vuetify's lazyload?
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>
Related videos on Youtube
Pruthvi Shetty
Updated on June 04, 2022Comments
-
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 over 3 yearsIf you can update Vuetify to
2.3.0-beta.3
, it has avirtual-scrollers
component that you could use. Here's documentation for it -
Zim almost 3 yearsbut the problem is that virtual-scroller doesn't work with grid rows/cols ... it only works with a single "column" of content
-
-
Pruthvi Shetty over 3 yearsthis 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 over 2 yearsThis 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 over 2 yearsI’m doing this way now: this.items.push[…loaded]