ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Javascript] Infinite Scroll (Height 속성)
    Front-End(Web)/Javascript 2021. 3. 7. 04:51
    반응형

    🤔 배경

    3차 프로젝트로 Nike 사이트 클론을 진행하면서, List 페이지를 연구하는테 아이템을 페이지네이션이 아닌 "인피니트 스크롤" 로 이어붙이는 로직으로 구성되어있는 것이었다. (아래는, 원본 사이트 영상) 

    출처 : 나이키 공식 홈페이지(https://www.nike.com/kr/ko_kr/w/men/fw/lifestyle)

    이를 구현하기 위해서, documentElement의 높이값 속성들을 통해 조건을 적용해야했고, 이를 간단히 정리하고 넘어가고자 글을 썼다.


    📒 scrollHeight / clientHeight / offsetHeight

    - document.documentElement

    위 세 가지 Height 속성값은 우선, document.documentElement 에서 가져올 수 있는 필드들이다.

    documentElement모든 비어있지 않은 HTML 문서에서, 항상 <html> 요소를 가르킨다.

     (모든 비어있지 않은 XML 문서에는, 항상 루트 요소를 가르킨다.)

     

    - Height 속성

    Height 속성을 설명하는 통용되는 그림이다. 우선 세 요소 모두 공통적으로 margin 값은 고려하지 않음을 알 수 있다.

    출처: https://blogpack.tistory.com/706

    • clientHeight : 요소의 내부 높이로, content + padding 값을 의미한다. 실제 보여지는 영역에 대한 높이다.
    • offsetHeight : 요소의 높이로, content + padding + border/스크롤바/테두리 까지 포함한 전체 높이이다.
    • scrollHeight : 요소의 전체(실제) 높이로, 보이지 않는 영역의 content + padding 까지 포함된 값이다.

     

    📒 ScrollTop() vs offset()

    우리가 사용해야되는 다른 메서드로, scrollTop() 이 있다. 이 개념과, 흔히 비교되는 offset() 을 알아보았다.

     

    - ScrollTop()

    window.scrollTop()

    페이지 최상단에서 현재 스크롤의 위치로, 다시 말하면 총 스크롤한 높이값을 의미한다. 상대적이고, 가변적인 값이다.

     

    - offset()

    section.offset()

    대상(요소)의 위치값이다. 고정적인 값이다. (절대적/불변적인 이유는, 반응형에서 브라우저를 늘이거나 줄일떄 변할 수 있다.)


    📒 Infinite Scroll 구현하기

     

    1) handleScroll 함수 만들기, useEffect 적용

    const handleScroll = () => {
      /* 스크롤에 따른 처리 로직 */
    }
    
    useEffect(() => {
      window.addEventListener('scroll', handleScroll);
      return () => window.removeEventListener('scroll', handleScroll);
    }, [handleScroll])
    • handleScroll() 함수는 스크롤에 따른 처리로직을 다루는 이벤트 핸들러 함수로, 스크롤 조건이나 처리구문 등이 들어간다.
    • 이 handleScroll() 함수를 useEffect Hooks를 통해 window 이벤트 핸들러로 추가해야 한다.
    • remove를 반환하는 이유는, useEffect의 이벤트 리스닝 혹은 리렌더에 따라 이벤트 리스너가 중첩되기 때문에 이전 리스너를 지워주는 동작을 같이 적용시켜줘야 하는 것이다.

     

    2) scroll 감지 로직

      const handleScroll =() => {
        const { scrollHeight, scrollTop, clientHeight } = document.documentElement;
        if (scrollTop + clientHeight >= scrollHeight) {
          dispatch(loadItemList(window.location.pathname.slice(5), {}))
          window.scrollTo(0, scrollTop-1)
        }
      }
    • documentElement(HTML) 에서 scrollHeight, clientHeight, scrollTop 속성값을 가져온다.
    • scrollHeight는 전체 높이, scrollTop은 현재까지 내려온 높이, clientHeight는 화면의 높이라고 생각하자.
    • scrollTop + clientHeight가 전체 높이값과 같거나 커지면(브라우저 바운스) 스크롤을 끝까지 내렸다는 의미이다.
    • 해당 조건에서 우리가 진행하고자 하는 로직을 적용하면 된다. (나의 경우, 새로운 데이터를 서버에서 디스패치하는 로직)

    scrollTo(x, y) 좌표값을 인자로 받으며, 해당 좌표로 브라우저 화면을 이동시켜주는 메서드이다.

    이를 적용시킨 이유는, 불러온 데이터가 같은줄에 배치될 경우 다시 인피니티 스크롤을 진행할 수 없다. (높이변동이 없으므로)

    이러한 경우를 대비해서, 마지막 위치에서 y축으로 1px만큼 올려주면서, 다시 스크롤을 진행하면 이벤트 핸들러가 발동되도록 한 것이다.


    스크롤 이벤트는 사실 이전에도 많이 적용했었다.

    window.pageYOffset 값에 따른 Navbar Fixed 제어, 스크롤 방향에 따른 상/하단 translateY 애니메이션 등등..

     

    그때마다, 어떤 Height 속성을 써야하는지 그 개념이 모호했는데 이번 기회에 확실히 정리했고,

    다음 기회에는 인피니티 스크롤을 구글링 없이 직접 만들수 있다는 자신감이 생겼다. (확실히, 포스팅을 하면 코드가 손에 익는다!! 🤌🤌)

     

    [출처]

    - Javascript MDN 공식문서 : developer.mozilla.org/ko/docs/Web/API/Element/scrollHeight  

    - 배하람 님의 블로그 : baeharam.github.io/posts/javascript/js-window/

     

    반응형
Designed by Tistory.