We've all been found guilty of spending a longer time than intended scrolling through our social media feeds. I mean, we keep entertaining that curiosity of what we'll find by simply sliding our fingers along the screen for one more time. The whole point is that users are persuaded to remain on your application when they experience unending content. So, if you're building an app that loads a huge amount of data (could be images, short videos, stories, or anything) and you'll need to lure users to remain, then giving your application a sense of infinite scroll is something to go for.
For this article, we'll create an infinite scroll with VueJs. All you'll need is
A basic understanding of Vue and
Axios installed locally
We'll be consuming API data from opentdb, (it's free and you don't need an authentication key) to display random questions and their answers. Here's a link to the full project on codesandbox
Step 1: Firstly, we'll fetch and house the API data that will be initially displayed on the app. To do this, we’ll create a data property that will eventually house our information, then we’ll retrieve the data by defining a function in the methods
object which we'll call in the mounted lifecycle hook.
App.vue
data() {
return {
questions: []
}
},
methods: {
getQuestions() {
axios
.get("https://opentdb.com/api.php?amount=5")
.then((response) => this.questions.push(...response.data.results))
.catch((error) => console.log(error))
},
mounted() {
this.getQuestions()
}
In this block, we simply sent a get
request to the API's endpoint, specifying we want to receive 5 objects per call. In this case, each object contains a question. Feel free to increase or reduce the objects per call by altering amount=5
.
If you take a little time to explore the information in the api's response
, you'll see that our priced information lives in response.data.results
. Hence we push response.data.results
unto the questions
data property we declared earlier.
Note: Adding
...
allows us to push the content ofresponse.data.results
individually and not the whole ofresponse.data.results
which is an object containing other objects. For this reason, we had to declare ourquestions
data property as an empty array instead of anull
value.
Step 2: We'll display the initial data retrieved from the API. To achieve this, we create a component to display each question in the questions
array as a card. Let's name the component Card
.
App.vue
<template> <div id="app"> <h2>Random questions and their answers</h2> <div v-for="(question, index) in questions" :key="index"> <Card :question="question" /> </div> </div> </template>
In this block, we loop through each object in the questions
array as question
, also retrieving its index in the array as index
which we'll use as a v-bind
key
. Each question
is then bound to our Card
component as a prop called question
.
Card.vue
<template> <div class="card"> <small class="card-header" category: {{ question.category }} <span>difficulty: {{ question.difficulty }}</span></small> <p>{{ computedQuestion }}</p> <small class="card-answer"> answer: <span>{{ question.correct_answer }}</span></small> </div> </template>
So we head over to our Card
component to render the received question
. For this article, We'll render just a few of the properties available in each question
. Feel free to add more, make yours more interesting!
Note: The
computedQuestion
rendered was written as acomputed
property to replace the special entities contained in our API's questions with their corresponding character.
On our browser, we'll get - Notice the length of the scroll while it displays just five questions.
Step 4: The moment we've all been waiting for! Our infinite scroll will work with a very easy logic - detect if the user has scrolled to the bottom of the window, and if they have, fire a function that'll retrieve more data.
App.vue
getMoreQuestions() {
window.onscroll = () => {
let bottomOfWindow =
document.documentElement.scrollTop + window.innerHeight ===
document.documentElement.offsetHeight;
if (bottomOfWindow) {
this.getQuestions()
}
}
}
document.documentElement.scrollTop
measures the distance between the element's top and its topmost visible content
window.innerHeight
is a property of the Window interface that returns the interior height of the window in pixels, including the height of the horizontal scroll bar, if present.
document.documentElement.offsetHeight
property returns the height of an element, including vertical padding and borders, as an integer.
By Implication, the point at which document.documentElement.offsetHeight
equals the sum of document.documentElement.scrollTop
and window.innerHeight
is the bottom of the window. Using if
statement, we fire getQuestions
as a call back function. Lastly, we call this function (getMoreQuestions
) in the mounted lifecycle hook.
App.vue
mounted() { this.getQuestions() this.getMoreQuestions() }
Now we get this on our browser -
Notice the length of the scroll, and compare it to what we had initially.
Just like that! Now, all you've got to do is keep scrolling, maybe you'll find the end of the page, who knows?
I'll be more than willing to attend to any question you may have, just drop by the comment section, thanks.