검색 결과 화면에서 유저가 브라우저 스크롤 바를 끝까지 이동시켰을 경우, 그 다음 페이지를 로딩하도록 만들어야 합니다.
<aside> 💡 IntersectionObserver MDN
Intersection Observer API는 타겟 요소와 상위 요소 또는 최상위 document 의 viewport 사이의 intersection 내의 변화를 비동기적으로 관찰하는 방법 https://developer.mozilla.org/ko/docs/Web/API/Intersection_Observer_API
</aside>
class SearchResult {
$searchResult = null;
data = null;
onClick = null;
constructor({ $target, initialData, onClick, onNextPage }) {
const $wrapper = document.createElement("section");
$wrapper.className = "SearchResultList";
this.$searchResult = document.createElement("ul");
this.$searchResult.className = "SearchResult";
$wrapper.appendChild(this.$searchResult);
$target.appendChild($wrapper);
this.data = initialData;
this.onClick = onClick;
this.onNextPage = onNextPage;
this.render();
}
setState(nextData) {
this.data = nextData;
this.render();
}
**listObserver = new IntersectionObserver((items, observer) => {
items.forEach(item => {
//아이템이 화면에 보일 때
if(item.isIntersecting){
//화면에 보이면 이미지를 로드한다. data-src 불러오기
//더미 이미지를 실제 데이터 src로 변환.
item.target.querySelector('img').src = item.target.querySelector('img').dataset.src;
//마지막 요소를 찾아낸다.
//전체 데이터의 길이 : this.data.length
let dataIndex = Number(item.target.dataset.index); //data-index 가져오기
//마지막 요소라면?
if(dataIndex + 1 === this.data.length){
//nextPage 호출.
this.onNextPage();
}
}
})
});**
**render() {
this.$searchResult.innerHTML = this.data
.map(
(cat, index) => `
<li class="item" data-index=${index}>
<img src="<https://via.placeholder.com/200x300>" alt="${cat.name}" data-src="${cat.url}" />
</li>
`
)
.join("");
this.$searchResult.querySelectorAll(".item").forEach(($item, index) => {
$item.addEventListener("click", () => {
this.onClick(this.data[index]);
});
this.listObserver.observe($item); //각 아이템에 observe 등록
});
}**
}
data-src라는 곳에 넣어줬다.data-index를 넣어 전체 목록 갯수 순차적으로 0~ 넣어준다.
마지막 리스트 여부 확인을 하기 위해 활용 됨.render() {
this.$searchResult.innerHTML = this.data
.map(
(cat, index) => `
<li class="item" **data-index=${index}**>
**<img src="<https://via.placeholder.com/200x300>" alt="${cat.name}"
data-src="${cat.url}" />**
</li>
`
)
.join("");
this.$searchResult.querySelectorAll(".item").forEach(($item, index) => {
$item.addEventListener("click", () => {
this.onClick(this.data[index]);
});
**this.listObserver.observe($item); //각 아이템에 observe 등록**
});
}
.SearchResult img {
width: 100%;
height: 100%;
min-height:300px;
object-fit: cover;
}
this.listObserver.observe($item); 리스트 랜더링을 하면서 각 요소를 옵저버 등록 시킨다.