무한 스크롤은 사용자가 페이지 하단에 도달했을 때, API가 호출되며 콘텐츠가 계속 로드되는 사용자 경험(UX) 방식입니다. 한 페이지 아래로 스크롤 하면 끝없이 새로운 화면을 보여주게 되고 이로 인해 많은 양의 콘텐츠를 스크롤 해서 볼 수 있습니다.
https://jsonplaceholder.typicode.com/
https://developer.mozilla.org/ko/docs/Web/API/EventTarget/removeEventListener
;
(function () {
'use strict'
const get = (target) => {
return document.querySelector(target)
}
})
})()
;
(function () {
'use strict'
const get = (target) => {
return document.querySelector(target)
}
//API url 불러오기
const getPost = async () => {
const API_URL = 'https://jsonplaceholder.typicode.com/posts'
const response = await fetch(API_URL) // async await를 사용하면 변수에 담을 수 있습니다
if (!response.ok) {
throw new Error('에러')
}
return await response.json()
}
const loadPost = async () => {
const response = await getPost() //리턴한 response.json을 받아옴
}
window.addEventListener('DOMContentLoaded', () => { //DOMContentLoaded발생시 실행
loadPost()
})
})()
const showPosts = (posts) => {
posts.forEach((post) => {
const $post = document.createElement('div')
$post.classList.add('post')
$post.innerHTML = `
<div class="header">
<div class="id"></div>
<div class="title"></div>
</div>
<div class="body">
</div>
`
});
}
const loadPost = async () => {
const response = await getPost() //리턴한 response.json을 받아옴
showPosts(response)
}
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>
`
});
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)
});
}
const limit = 10
const getPost = async () => {
const API_URL = `https://jsonplaceholder.typicode.com/posts?_limit=${limit}`
...
}
const onScroll = () => {
const {scrollTop, scrollHeight, clientHeight} = document.documentElement
if (scrollTop + clientHeight >= scrollHeight - 5) { //간격을 주기 위해 5px을 뺍니다.
loadPost()
}
}
window.addEventListener('DOMContentLoaded', () => {
loadPost()
window.addEventListener('scroll', onScroll)
})
})()
let page = 1
//API url 불러오기
const getPost = async () => {
const API_URL = `https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=${limit}`
...
}
const onScroll = () => {
const {scrollTop, scrollHeight, clientHeight} = document.documentElement
if (scrollTop + clientHeight >= scrollHeight - 5) { //간격을 주기 위해 5px을 뺍니다.
page++
loadPost()
}
}
const end = 100
let total = 10
const onScroll = () => {
const {scrollTop, scrollHeight, clientHeight} = document.documentElement
if(total === end) {
return
}
if (scrollTop + clientHeight >= scrollHeight - 5) { //간격을 주기 위해 5px을 뺍니다.
page++
total += 10
loadPost(currentPage, limit)
return
}
}
if(total === end) {
window.removeEventListener('scroll', onScroll)
return
}
const $loader = get('.loader')
const showLoader = () => {
$loader.classList.add('show')
}
const hideLoader = () => {
$loader.classList.remove('show')
}
const loadPost = async () => {
//로딩 엘레멘트를 보여줌
showLoader()
try {
const response = await getPost() //리턴한 response.json을 받아옴
showPosts(response)
} catch (error) {
console.error(error)
} finally {
hideLoader()
//로딩 엘레멘트를 사라지게 함
}
}