There are plenty of ways to create an infinite scroll list in Vue.js. Some of the popular methods are based on one of the following premises:
- Calculating the list height, and checking if the scroll top position of the last item is less than half of the list height. In such cases, we can make another API call to load more data on scroll.
- Making use of the Intersection Observer API, and if the last item of the list is visible on the screen, we make the API call
- Making use of a library that uses Intersection Observer API
Let’s have a look at how we can use a library to quickly create an infinite scroll list.
First of all, we need to install the library called vue-infinite-scroll:
npm install vue-infinite-scroll -s
Once installed, we can now either register the component globally or locally. If registered globally, we’ll be able to use the component anywhere we want in our app without having to import it again and again. Here in this example, we’re registering it globally.
Here’s the main.js file:
import Vue from "vue";
import App from "./App.vue";
import infiniteScroll from "vue-infinite-scroll";
Vue.use(infiniteScroll);
Vue.config.productionTip = false;
new Vue({
render: (h) => h(App)
}).$mount("#app");
Code language: JavaScript (javascript)
After that, we can use it in any component. Here’s a component using the same:
<template>
<div id="app">
<div class="np-credits">wwww.nightprogrammer.com</div>
<h1>Infinite scroll example</h1>
<div
v-infinite-scroll="loadMoreItems"
infinite-scroll-disabled="isLoading"
infinite-scroll-distance="10"
>
<div v-for="(item, i) of itemsList" :key="i" class="np-item">
{{ item.id }}
</div>
</div>
<div v-if="isLoading">Loading...</div>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
itemsList: [],
isLoading: false,
};
},
methods: {
loadMoreItems() {
this.isLoading = true;
setTimeout(() => {
this.itemsList = [
...this.itemsList,
...Array(20)
.fill()
.map(() => {
return { id: parseInt((Math.random() * 10000).toString(), 10) };
}),
];
this.isLoading = false;
}, 500);
},
},
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
padding: 24px;
}
.np-credits {
font-size: 12px;
margin-top: 12px;
color: #4b4b4b;
}
.np-item {
padding: 10px;
border: 1px solid rgb(255, 83, 232);
margin: 10px 0;
}
</style>
Code language: HTML, XML (xml)
In the code above, we used the component in the template through lines 5 to 14. We’ve initiated two reactive states named itemsList and isLoading.
- itemsList: To store a list of values
- isLoading: A boolean to store whether or not the list is loading
Then we have a method named loadMoreItems. This is fired whenever the last element of the list is visible. It’ll also get fired when the list is empty. We’ve created some dummy data with a list of 40 items containing random numbers as id’s. We’ve then displayed this data on line 10 using the for loop. On line 14 we’ve shown a ‘Loading…’ text whenever isLoading state is true. Of course, we can use a custom CSS loader, or even an image or SVG.
Here’s what the above code would look like in action: