스크롤이 바닥에 닿게 되면
맨 처음에 데이터를 불러오는 함수를 만들어줍니다.
const getPosts = async (page, limit) => {
const API_URL = `https://jsonplaceholder.typicode.com/posts`
const response = await fetch(API_URL)
if (!response.ok) {
throw new Error('에러가 발생했습니다.')
}
return await response.json()
}
console.log를 통해 가져온 데이터를 확인합니다.
const loadPosts = async () => {
const response = await getPosts(page, limit)
console.log(response);
}
포스트 데이터를 HTML 요소로 렌더링하는 함수를 만들어줍니다.
const $posts = get('.posts')
const showPosts = (posts) => {
posts.forEach((post) => {
const $post = document.createElement('div')
$post.classList.add('post')
$post.innerHTML = `
<div class="header">
<div class="id">${post.id}.</div>
<div class="title">${post.title}</div>
</div>
<div class="body">${post.body}</div>
`
$posts.appendChild($post)
})
}
그러면 데이터를 잘 가지고 온 걸 확인할 수 있습니다.
이제 스크롤이 바닥에 닿았을 때 데이터를 불러오도록 변경하겠습니다.
한번에 보여주는 데이터를 10개로 지정해주고 url를 변경해줍니다.
const limit = 10
const getPosts = async (page, limit) => {
const API_URL = `https://jsonplaceholder.typicode.com/posts?_limit=${limit}`
const response = await fetch(API_URL)
if (!response.ok) {
throw new Error('에러가 발생했습니다.')
}
return await response.json()
}
스크롤 끝을 감지하도록 스크롤 이벤트를 생성합니다.
window.addEventListener('DOMContentLoaded', () => {
loadPosts()
window.addEventListener('scroll', handleScroll)
})
5px 정도 닿으면 새로운 데이터를 불러오도록 5px를 빼줍니다.
const onScroll = () => {
const { scrollTop, scrollHeight, clientHeight } = document.documentElement
if (scrollTop + clientHeight >= scrollHeight - 5) {
loadPosts(currentPage, limit)
}
}
이 페이지를 추가할건데 데이터를 10개 들어가 있는 페이지를 말합니다.
페이지 변수에 1를 넣어주고 url 주소에도 page를 추가해줍니다.
let page = 1
const getPosts = async (page, limit) => {
const API_URL = `https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=${limit}`
const response = await fetch(API_URL)
if (!response.ok) {
throw new Error('에러가 발생했습니다.')
}
return await response.json()
}
바닥에 닿을 떄마다 페이지를 추가해줍니다.
const onScroll = () => {
const { scrollTop, scrollHeight, clientHeight } = document.documentElement
if (scrollTop + clientHeight >= scrollHeight - 5) {
loadPosts(currentPage, limit)
page++
}
}
여기서 문제가 발생할 수 있는 건 페이지를 다 가지고 왔는데도 page는 무한대로 증가합니다. 제한을 주기 위해서 총개수를 변수에 저장해줍니다.
total는 여태까지 불러온 데이터의 개수이고 end는 데이터의 총개수를 저장해줍니다.
let total = 10
const end = 100
그리고 total의 개수와 end의 개수가 같으면 리스트는 다 나온거지 때문에 증가되지 않도록 스크롤 이벤트를 없애줍니다.
const handleScroll = () => {
const { scrollTop, scrollHeight, clientHeight } = document.documentElement
if (total === end) {
window.removeEventListener('scroll', handleScroll)
return
}
if (scrollTop + clientHeight >= scrollHeight - 5) {
currentPage++
total += 10
loadPosts(currentPage, limit)
return
}
}
지금까지 무한 스크롤을 완성했고 디테일한 부분을 만들겠습니다.
리스트가 로드될 때 로딩 이미지가 나와야 합니다.
응답을 받기 전까지 로딩이 나오도록하고 응답을 받으면 로딩을 없지도록 코드를 짰습니다.
const loadPosts = async (page, limit) => {
showLoader()
try {
const response = await getPosts(page, limit)
showPosts(response)
} catch (error) {
console.error(error.message)
} finally {
hideLoader()
}
}
이제 loader라는 함수를 선언하고 hideLoader일 때는 css를 없애고 showLoader일 때는 css를 추가해줍니다.
const $loader = get('.loader')
const hideLoader = () => {
$loader.classList.remove('show')
}
const showLoader = () => {
$loader.classList.add('show')
}
무한스크롤을 완성했습니다!!!
아래는 총 코드입니다.
;(function () {
'use strict'
const get = function (target) {
return document.querySelector(target)
}
let currentPage = 1
let total = 10
const limit = 10
const end = 100
const $posts = get('.posts')
const $loader = get('.loader')
const hideLoader = () => {
$loader.classList.remove('show')
}
const showLoader = () => {
$loader.classList.add('show')
}
const showPosts = (posts) => {
posts.forEach((post) => {
const $post = document.createElement('div')
$post.classList.add('post')
$post.innerHTML = `
<div class="header">
<div class="id">${post.id}.</div>
<div class="title">${post.title}</div>
</div>
<div class="body">${post.body}</div>
`
$posts.appendChild($post)
})
}
const getPosts = async (page, limit) => {
const API_URL = `https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=${limit}`
const response = await fetch(API_URL)
if (!response.ok) {
throw new Error('에러가 발생했습니다.')
}
return await response.json()
}
const loadPosts = async (page, limit) => {
showLoader()
try {
const response = await getPosts(page, limit)
showPosts(response)
} catch (error) {
console.error(error.message)
} finally {
hideLoader()
}
}
const handleScroll = () => {
const { scrollTop, scrollHeight, clientHeight } = document.documentElement
if (total === end) {
window.removeEventListener('scroll', handleScroll)
return
}
if (scrollTop + clientHeight >= scrollHeight - 5) {
currentPage++
total += 10
loadPosts(currentPage, limit)
return
}
}
window.addEventListener('DOMContentLoaded', () => {
loadPosts(currentPage, limit)
window.addEventListener('scroll', handleScroll)
})
})()
'자바스크립트' 카테고리의 다른 글
[JavaScript] 모달 띄우기 (0) | 2025.03.24 |
---|---|
[JavaScript] 이미지 슬라이드 (0) | 2025.03.20 |
[JavaScript] Scroll에 따른 progressbar 만들기 (0) | 2025.03.18 |
[JavaScript] 클래스 (0) | 2025.03.17 |
[JavaScript] 프로토타입 (0) | 2025.03.14 |