타겟 요소와 상위 요소 또는 최상위 document의 viewport 사이의 intersection 내의 변화를 비동기적으로 관찰하는 방법입니다.
new IntersectionObserver(callback[, options]);
대상 요소의 보이는 영역 비율이 넘을 때 호출할 함수입니다. callback은 두 개의 매개변수(entries, observer)를 받습니다.
감지기를 조절할 수 있는 객체입니다.
지정한 root 내에서 주시중인 요소의 가시성이 threshold를 위아래로 넘어가는 경우를 감지할 수 있는 새로운 IntersectionObserver.observe() 메서드를 호출해서 새로운 요소를 주시할 수 있습니다.
쓰로틀링 개념을 적용하고 IntersectionObserver를 사용하여 무한 스크롤을 구현해 보았습니다.
//HTML
<section class="data-list">
</section>
// JS
const renderBox = (start, end, bgColor) => {
for (let i = start; i < start + end; i++) {
const div = document.createElement('div');
div.setAttribute('class', 'dummy-box');
div.style.height = '300px';
div.style.lineHeight = '300px';
div.style.border = '1px';
div.style.borderColor = 'black';
div.style.borderStyle = 'solid';
div.style.backgroundColor = bgColor;
div.innerHTML = 'dummyBox' + i;
document.querySelector('.data-list').appendChild(div);
}
}
renderBox(0, 10);
const loadMoreBox = (moreCnt) => {
let dummyBoxCnt = document.querySelectorAll('.dummy-box').length;
const bgColor = dummyBoxCnt > 60 ? 'skyblue' : 'orange';
renderBox(dummyBoxCnt, moreCnt, bgColor);
}
const ioCallback = (entries, io) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
io.unobserve(entry.target);
setTimeout(() => {
loadMoreBox(10);
observeLastItem(io, document.querySelectorAll('.dummy-box'));
}, 200);
}
});
};
const observeLastItem = (io, items) => {
const lastItem = items[items.length - 1];
io.observe(lastItem);
};
const io = new IntersectionObserver(ioCallback, {threshold: 0.7});
observeLastItem(io, document.querySelectorAll('.dummy-box'));
observerLastItem 을 함수로 분리하였고 ioCallback 을 통해 실행 재실행 시키면서 감시대상을 맨 마지막 요소로 변경해주었습니다.