참고: 자바스크립트: IntersectionObserver (2) 무한 스크롤(Infinite Scroll) 구현 (라이브러리 없이)

스크롤 이벤트를 하면 이벤트 타겟에 scrollingElement라는 프로퍼티가 있는데 이것을 통해 현재 스크롤 상태와 관련된 정보를 얻을 수 있습니다.

또는 document,documentElement || document.body 에서도 가져올 수 있습니다.

 

  • clientHeight : 웹 브라우저 창(내용이 보여지는 영역)의 높이입니다.
  • scrollTop : 현재 스크롤된 부분의 맨 위의 높이입니다. (=현재 스크롤의 위치) 스크롤을 하지 않았다면 0이고. 스크롤을 할 때마다 값이 증가합니다.
  • scrollHeight : 문서의 총 높이 (= 스크롤 대상의 총 높이) 입니다.

 

스크롤이 끝까지 된 경우, clientHeightscrollTop의 합은 scrollHeight와 같거나 더 크게 됩니다. 이러한 특성을 이용하여 스크롤이 끝까지 되었으면 추가 데이터를 로딩하면 됩니다.

const contents = document.querySelector(".contents") // tbody 태그
let paraIndex = 1

async function fetchLorem() {
    const response = await fetch("https://baconipsum.com/api/?type=meat-and-filler&paras=18")
    const data = await response.json()
    
    for(let i = 0; i < 6; i++) {
        const $tr = document.createElement("tr")
        $tr.innerHTML = `<td width='50' align='center'>${paraIndex++}</td>
                            <td>${data[(i * 3)]}<br>${data[(i * 3) + 1]}<br>${data[(i * 3) + 2]}</td>`
        contents.appendChild($tr)
    }
    
}

function debounce(callback, limit = 100) {
    let timeout
    return function(...args) {
        clearTimeout(timeout)
        timeout = setTimeout(() => {
            callback.apply(this, args)
        }, limit)
    }
}

fetchLorem()

// ===== 무한 스크롤 (스크롤 이벤트) =====
document.addEventListener("scroll", debounce(e => {
    
    // clientHeight : 웹 브라우저 창의 높이
    // scrollTop : 현재 스크롤된 부분의 맨 위의 높이
    // scrollHeight : 문서의 총 높이 (= 스크롤의 총 높이)
    // 스크롤의 마지막에 도달 : clientHeight + scrollTop >= scrollHeight
    
    const { clientHeight, scrollTop, scrollHeight } = e.target.scrollingElement
    if(clientHeight + scrollTop >= scrollHeight) {
        fetchLorem()
    }
}, 200))

 

Debounce 적용은 필수는 아니지만, 스크롤링 이벤트는 1픽셀마다 이벤트를 발생시키기 때문에 성능 하락의 우려가 있으므로 되도록이면 적용하는 것이 좋습니다.

문의 | 코멘트 또는 yoonbumtae@gmail.com


카테고리: WEB: Frontend


1개의 댓글

자바스크립트: 스크롤 상태 표시기 (스크롤 인디케이터, 라이브러리 없이 구현) - BGSMM · 2021년 2월 18일 10:30 오후

[…] 자바스크립트: 무한 스크롤 (스크롤 이벤트 이용, 라이브러리 없이) […]

답글 남기기

Avatar placeholder

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다