무한스크롤 바닐라 js로 먼저 만들어보기

미마모코딩·2022년 10월 13일
0

무한스크롤

목록 보기
1/2
post-thumbnail

오늘은 무한스크롤을 만들어볼것이고 dom요소를 간만에 사용해볼것이다.

미리 IntersectionObserver의 배경지식을 공부하면 좋은데 링크텍스트 이 블로그를 참고해서 배경지식을 습득하고 아래 예제를 공부해보자.

hmtl소스코드

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .card_container {
        display: flex;
        flex-direction: column;
        gap: 1rem;
        align-items: flex-start;
      }
      .card {
        background-color: white;
        border: 1px solid black;
        border-radius: 0.25rem;
        padding: 0.5rem;
        transform: translateX(100px);
        opacity: 0;
        transition: 150ms;
      }
      .card.show {
        opacity: 1;
        transform: translateY(0);
      }
    </style>
  </head>
  <body>
    <div class="card_container">
      <div class="card">This is a first card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a card</div>
      <div class="card">This is a Last card</div>
    </div>
  </body>
  <script src="practice.js"></script>
</html>


js 소스코드
<script>
const cards = document.querySelectorAll(".card");
const cardContainer = document.querySelector(".card_container");

const observer = new IntersectionObserver(
  (entries) => {
    entries.forEach((entry) => {
      entry.target.classList.toggle("show", entry.isIntersecting);
      if (entry.isIntersecting) observer.unobserve(entry.target); //이 과정이 없다면
      //콜백이 계속 실행될것임
    });
  },
  {
    rootMargin: "100px",
  }
);

cards.forEach((card) => {
  observer.observe(card);
}); // document.querySelectorAll로잡은 card의 배열들을 쪼개 각각 요소를 전부 추적하게 만듦


const lastObserver = new IntersectionObserver((entries) => {
  const lastCard = entries[0];
  if (!lastCard.isIntersecting) return; //마지막 카드가 뷰포트에 들어와있지않다면 함수실행 x
  loadMoreElem(); //뷰포트에 들어왔다면 요소추가
  lastObserver.unobserve(lastCard.target); //지난 마지막요소 취소
  lastObserver.observe(document.querySelector(".card:last-child")); //추가된 
  //newCard의 마지막요소를 추적하고 반복적으로 호출됨
});
lastObserver.observe(document.querySelector(".card:last-child")); //html의 
//card요소중 제일 마지막요소를 잡아와 추적함

function loadMoreElem() {
  for (let i = 0; i < 10; i++) {
    const newCard = document.createElement("div");
    newCard.textContent = "NEW CARD";
    newCard.classList.add("card");
    observer.observe(newCard);
    cardContainer.append(newCard);
  }
}
</script>

우리가 먼저 IntersectionObserver를 공부하고 적용하려면 설계하려는 틀부터 구체화시키는게 좋다.

어느 부분에서 추적을 멈출건지 어느 부분에서 추적을 시작할건지 이런 것부터 말이다.

코드 해석

js소스코드에서 나는 html의 card라는 클레스를 가진 녀석들을 전부 쿼리셀럭터로 잡아냈다.

그리고 컨테이너도 잡아냈다.

옵저버라는 변수를 선언하고 new intersectionObserver를 생성하고 초기화했다.
이 과정에서 intersectionObserver는 callback과 option를 가진다.
현재 추적중인 녀석들이 뷰포트 안으로 들어오는 순간 콜백이 실행된다.

콜백이 실행되었을때 show라는 클레스가 붙게되고 다시 반복적으로 저 콜백이 호출되지 않게 하기위해 아래 코드를 작성해주었다.

if (entry.isIntersecting) observer.unobserve(entry.target);

위 코드를 해석하기 위해 우리는 아래코드를 먼저 알아야한다.

const io = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    console.log(entry) // entry is 'IntersectionObserverEntry'
  })
}, options)
io.observe(element)

우리가 추적한 elem가 어디있나하면 entries를 forEach로 쪼개면 entry들이 있을것이다.entry.target에 현재 우리가 추적하는 요소가 담겨있다.
entries는 IntersectionObserverEntry 인스턴스의 배열이다.
IntersectionObserverEntry는 읽기 전용(Read only)의 다음 속성들을 포함한다.
boundingClientRect: 관찰 대상의 사각형 정보(DOMRectReadOnly)
intersectionRect: 관찰 대상의 교차한 영역 정보(DOMRectReadOnly)
intersectionRatio: 관찰 대상의 교차한 영역 백분율(intersectionRect 영역에서 boundingClientRect 영역까지 비율, Number)
isIntersecting: 관찰 대상의 교차 상태(Boolean)
rootBounds: 지정한 루트 요소의 사각형 정보(DOMRectReadOnly)
target: 관찰 대상 요소(Element)
time: 변경이 발생한 시간 정보(DOMHighResTimeStamp)

이미 추적이 끝나고 콜백이 실행도 특정 함수를 호출한 elem들은 추적을 꺼주고 다시 콜백이 실행되지 않게 만든다.

라스트 요소는 card:last-child를 사용해 마지막 요소를 특정하고 이 카드를 추적한다.

그리고 마지막 요소가 뷰포트안에 들어오지 않았다면 콜백함수는 실행되지 않고 들어오게 된다면 새로운 요소들을 만들고 기존의 마지막요소는 추적을 종료한다.

새롭게 추가된 요소의 마지막 요소를 새롭게 추적해서 끊임없이 새로운 요소를 만들어 무한스크롤을 구현한다

오늘은 바닐라 자바스크립트로 무한스크롤을 만들어봤다 다음시간엔 react로 구현해보자 .

0개의 댓글