Infinite Scroll in Nuxt.js
Because of better UX, you can see Infinite Scroll everywhere. Depending on the context it’s a wonderful solutions for adding new content to the page.
There are basically two ways you can implement the Infinite Scroll in your project.
- Vanilla JS
- Plugins.
After searching for a while, there wasn’t any easy way to do it with pure JS code.
So I used a plug in called Vue-infinite-loading, it’s great to use and has nice animations.
Implementing wasn’t smooth for me, so I decided to write an article to save time for others.
Edit on 10/19: If you are using Vuetify, it’s easiest with v-intersect. Available from the Vuetify version 2.1 or more.
Here’s the demo :
This article will be divided in two parts.
- Set up a Nuxt.js page with the json:api (optional)
- Implement the Infinite Scroll
Part 1
(This part is optional. If you have already an existing project, you can jump to the next part)
Let’s create a Nuxt.js project as written in the official document. Here’s a quick GIF:
Here’s some basic codes to set up a working page. I’m not explaining the code because this should make sense if you know Nuxt.js. (And if you don’t, you should follow a beginner tutorial to create a basic app and then come here :) )
1.1
Delete all the files in the pages
except the index.vue
and change the code into the following ones:
<template>
<v-flex>
<v-container fluid grid-list-lg class="mt-5">
<posts/>
</v-container>
</v-flex>
</template><script>
import posts from "~/components/Posts.vue";export default {
components: { posts }
};
</script>
(I am using Vuetify framework for design. So that’s why you are seeing the <v-something>
tags. The “ v” is for Vuetify components.)
1.2
Now, Delete all the files in the components
folder and create a new component named Posts.vue
and paste the following codes:
<template>
<v-card flat>
<v-layout row wrap>
<v-flex v-for="(title, index) in titles" :key="index">
<v-card flat hover class="white pb-2 mb-1 pl-2">
<v-layout>
<v-flex xs10>
<div class="py-2">{{ title.body }}</div>
</v-flex>
</v-layout>
</v-card>
</v-flex>
</v-layout>
</v-card>
</template>
<script>
import axios from "axios"; export default {
name: "Posts",
data() { return {
titles: [], page: 1 };
},
computed: {
url() { return "https://jsonplaceholder.typicode.com/posts?_page=" + this.page; } },
created() {
this.fetchData(); },
methods: {
async fetchData() { const response = await axios.get(this.url); this.titles = response.data; } }
};
</script> <style scoped>
.theme--light.v-card { background-color: #f5f5f5; }
</style>
1.3
In the layouts/default.vue
file paste the following code:
<template>
<v-app>
<nuxt class="mb-5"/>
</v-app>
</template>
If you followed all the steps correctly your project will look like this:
You can see in the sandbox that there are a few posts in the page which I am calling from an API. And right now there are no Infinite Scroll.
The basic part is complete. Now with that out of the way.
Part 2
Next, install the Vue-infinite-loading here with npm.
npm install vue-infinite-loading -S
Then in the plugins
folder , create a blank file named infiniteloading.js
and paste the following code:
import Vue from 'vue'
import InfiniteLoading from 'vue-infinite-loading'
Vue.component('infinite-loading', InfiniteLoading)
Now let’s add the plugin file in the nuxt.config.js
.
plugins: [
{ src: '~/plugins/infiniteloading', ssr: false }
]
The infinite loading component set up is finished. Yay.
2.1
Now let’s add the following Infinite Scroll component at the bottom of the posts.vue component.
<infinite-loading
spinner="spiral"
@infinite="infiniteScroll"
></infinite-loading>
Bottom of the page because whenever this component will be visible in the browser, it will trigger the selected method. In this case, the method is infiniteScroll
which we will write soon below.
So if it is in the upper side of the page , it will trigger the method as soon as the page is created which we do not want because we haven’t scrolled yet.
I have selected the spinner type as spiral. You can change it to other type. Please check out the official documents of infinite loading component to choose other designs.
2.2
Add the following function in the methods:
and you are done.
infiniteScroll($state) {setTimeout(() => {
this.page++axios.get(this.url)
.then((response) => { if (response.data.length > 1) {
response.data.forEach((item) => this.titles.push(item))
$state.loaded() } else { $state.complete() } }).catch((err) => {console.log(err)})}, 500)
setTimeout
is for to call the code a little bit late.
axios.get
is getting the data from the api.
response.data.length
is to check whether it’s getting data, if there is no data it will be false.
response.data.forEach((item) => this.title.push(item))
is adding every new item from array to the title
$state.loaded(),$state.complete()
is the animation of loading the component.
The complete code is available in this GitHub repository. Originally published here.