[JS]Passing arguments to event handlers, The Intersection Observer API

Hyodduru ·2021년 12월 22일
0

JavaScript

목록 보기
47/60
post-thumbnail

강의 출처 : The Complete JavaScript Course 2022 Jonas (Udemy)

Passing Arguments to Event Handlers

event handler에 event 이외의 추가 인자를 넣어야하는 상황 해결하기 + Refactoring 꿀팁(흔한 로직)

  1. 반복적인 코드를 함수로 만든다.
  2. 반복되지 않는 부분을 인자로 받는다. ex) opacity
    but! eventHandler 함수는 e 만을 인자로 받음!
    callback 함수를 bind로 묶어주고 그 안의 인자에 opacity넣어주기. bind함수는 그 인자에 this를 부여한다.

Menu fade animation

const handleHover = function (e) {
  if (e.target.classList.contains('nav__link')) {
    const link = e.target;
    const siblings = link.closest('.nav').querySelectorAll('.nav__link');
    const logo = link.closest('.nav').querySelector('img');

    siblings.forEach(el => {
      if (el !== link) {
        el.style.opacity = this;
      }
      logo.style.opacity = this;
    });
  }
};

//Passing "argument" into handler
nav.addEventListener('mouseover', handleHover.bind(0.5));

nav.addEventListener('mouseout', handleHover.bind(1));

The Scroll Event

Implementing a Sticky Navigation

const initialCoords = section1.getBoundingClientRect();

window.addEventListener('scroll', e => {
   //console.log(window.scrollY); //viewport의 top에서 page의 top까지
   if (window.scrollY > initialCoords.top) {
     nav.classList.add('sticky');
   } else {
     nav.classList.remove('sticky');
   }
 });

참고) scroll event는 되도록 쓰지 않는 것이 좋음. 너무 빈번하게 일어나므로.

The Intersection Observer API

entries : an array of threshold 로 볼 수도 있음.

const obsCallback = function (entries, observer) {
  entries.forEach(entry => console.log(entry));
};
const obsOptions = {
  root: null, //null : entire view port. root : intersecting 하고 싶은 target
  threshold: [0, 0.2], //view port의 percent  => 이 percent 이상으로 intersecting 하면 callback 함수를 실행한다.
  rootMargin : '10px' //visual margin of root(target element).
};

const observer = new IntersectionObserver(obsCallback, obsOptions);
observer.observe(section1);
const header = document.querySelector('.header');
const navHeight = nav.getBoundingClientRect().height;

const stickyNav = function (entries) {
  const [entry] = entries; // = entry = entries[0] destructuring
  if (!entry.isIntersecting && entry.intersectionRatio === 0) {
    nav.classList.add('sticky');
  } else {
    nav.classList.remove('sticky');
  }
};
const headerObserver = new IntersectionObserver(stickyNav, {
  root: null,
  threshold: 0,
  rootMargin: `-${navHeight}px`,
});
headerObserver.observe(header);

Revealing Elements on Scroll

The Intersection Observer API를 이용하여 스크롤 할 때마다 해당 section별 효과 주기

const allSections = document.querySelectorAll('.section');
const revealSection = function (entries, observer) {
  const [entry] = entries; // threshold 하나만 있으므로.
  if (!entry.isIntersecting) return;
  entry.target.classList.remove('section--hidden');
  sectionObserver.unobserve(entry.target); // 한번만 실행하고자. 더이상 관찰할 이유가 없음.
};
const sectionObserver = new IntersectionObserver(revealSection, {
  root: null,
  threshold: 0.15,
});

allSections.forEach(section => {
  sectionObserver.observe(section);
  section.classList.add('section--hidden');
});

Lazy Loading Images

The Intersection Observer API를 이용하여 이미지 로딩 기능 구현하기
Lazy loading images

const imgTargets = document.querySelectorAll('img[data-src]');

const loadImg = function (entries, observer) {
  const [entry] = entries;
  console.log(entry);
  if (!entry.isIntersecting) return;

  //Replace src with data-src
  entry.target.src = entry.target.dataset.src;
  entry.target.addEventListener('load', () => {
    entry.target.classList.remove('lazy-img'); 
    // img가 다 load 된 다음에 실행시키는 것이 좋다.  
    //느린 컴퓨터에서는 src가 바뀌기도 전에 blur 가 없어지기도 하므로,,
  });
  observer.unobserve(entry.target);
};
const imgObserver = new IntersectionObserver(loadImg, {
  root: null,
  threshold: 0,
  rootMargin: '200px',
});

imgTargets.forEach(img => imgObserver.observe(img));

이미지의 src를 대체한 후 load event를 실행시켜주는 점 기억할 것! 이미지가 다 load된 후 효과주기 위해.

profile
꾸준히 성장하기🦋 https://hyodduru.tistory.com/ 로 블로그 옮겼습니다

0개의 댓글