Javascript Study

Javascript 이벤트(추가, 삭제, 객체, 옵션, 버블링, 위임)

짤진이 2023. 9. 9. 21:37
반응형

addEventListener()

대상에 지정한 이벤트가 발생했을 함수(Handler) 호출된다

const parentEl = document.querySelector(".parent");
const childEl = document.querySelector(".child");

parentEl.addEventListener("click", () => {
  console.log("parent!");
});
childEl.addEventListener("click", () => {
  console.log("child!");
});

 

removeEventListener()
대상에 지정한 이벤트를 제거한다.

removeEventListener를 사용할 때 콜백 함수 부분에  따로 설정한 함수가 들어가지 않으면 그 함수를 지정하는 줄 모르고 지우지 않는다.

const parentEl = document.querySelector(".parent");
const childEl = document.querySelector(".child");

const handler = () => {
  console.log("parent!");
};

parentEl.addEventListener("click", handler);
childEl.addEventListener("click", () => {
  parentEl.removeEventListener("click", handler);
});
// remove로 지워주려면 callback 함수가 아닌 handler라는 함수를 따로 만들어줘야함

 

이벤트 객체
이벤트 객체는 대상에서 발생한 이벤트 정보를 담고 있다

parent 부분을 클릭하면 parent,parent가 출력되지만 child 부분을 클릭하면 child, parent가 출력된다.

그 이유는 target은 지금 누른 것을 호출하지만 currentTarget은 등록되어 있는 부분 즉 조상을 호출하기 때문이다.

const parentEl = document.querySelector(".parent");

parentEl.addEventListener("click", (event) => {
  console.log(event.target, event.currentTarget);
});
parentEl.addEventListener("wheel", (event) => {
  console.log(event);
});
// target, currentTarget => 현재 타겟, 등록된 타겟

const inputEl = document.querySelector("input");
//input 태그안에 눌리는 키 출력
inputEl.addEventListener("keydown", (event) => {
  console.log(event.key);
});

 

기본 동작 방지
마우스 휠의 스크롤 동작을 방지한다.

event.precentDefault()를 사용하면 적용된 이벤트 'wheel'이 실행이 안되지만 콘솔창에 'wheel!'은 출력이 된다

마찬가지로 a태그에도 적용해주면 클릭해서 다른 페이지로 이동하진 않지만 콘솔창에는 출력이 된다.

const parentEl = document.querySelector(".parent");
parentEl.addEventListener("wheel", (event) => {
  event.preventDefault(); //스크롤이 안됨, wheel!은 뜸
  console.log("wheel!");
});

//페이지 이동 방지
const anchorEl = document.querySelector("a");
anchorEl.addEventListener("click", (event) => {
  event.preventDefault(); //a태그가 실행 안됨
  console.log("click");
});

 

이벤트 전파(버블) 정지

event.stopPropagation()을 적용하기 전 a태그를 클릭하면 anchor, child, parent, body, window 순서로 출력이 된다.

event.stopPropagation()을 적용하면 적용된 부분까지만 출력되므로 parent부분에서 사용했다면 anchor, child, parent까지 나온다.

const parentEl = document.querySelector(".parent");
const childEl = document.querySelector(".child");
const anchorEl = document.querySelector("a");

window.addEventListener("click", (event) => {
  console.log("Window");
});
document.body.addEventListener("click", (event) => {
  console.log("body");
});
parentEl.addEventListener("click", (event) => {
  console.log("parent");
  event.stopPropagation(); //버블링 정지
});
childEl.addEventListener("click", (event) => {
  console.log("child");
});
anchorEl.addEventListener("click", (event) => {
  console.log("anchor");
});
// 버블링 정지 전 => anchor,child,parent,body,window
// 버블링 정지 후 => anchor, child, parent
//capture를 사용하면 제일 먼저 호출함

 

addEventListener() 뒤에 capture : true라는 객체를 추가해주면 그 부분이 가장 먼저 실행이된다.

원래는 anchor, child parent 순서대로 출력이 되야하지만 window, anchor, child , parent로 출력이 된다.

const parentEl = document.querySelector(".parent");
const childEl = document.querySelector(".child");
const anchorEl = document.querySelector("a");

window.addEventListener("click", (event) => {
  console.log("Window");
},{capture : true});
document.body.addEventListener("click", (event) => {
  console.log("body");
});
parentEl.addEventListener("click", (event) => {
  console.log("parent");
  event.stopPropagation(); //버블링 정지
});
childEl.addEventListener("click", (event) => {
  console.log("child");
});
anchorEl.addEventListener("click", (event) => {
  console.log("anchor");
});
// 버블링 정지 전 => anchor,child,parent,body,window
// 버블링 정지 후 => anchor, child, parent
//capture를 사용하면 제일 먼저 호출함

 

기본 동작과 핸들러 실행 분리

아래 코드에서 기본으로 동작하는 wheel과 1000까지 호출하는 함수가 있는데 passive : true라는 속성이 없다면 부하가 걸려 window 화면 내에서 버벅거릴 수 있다. passive : true가 있다면 아무리 큰 수라도 실행을 분리했기 때문에 멈춤 없이 동작한다.

const parentEl = document.querySelector(".parent");

parentEl.addEventListener(
  "wheel",
  () => {
    console.log("parent");
    for (let i = 0; i < 1000; i++) {
      console.log(i);
    }
  },
  {
    passive: true,
  }
);
//passive가 true면 wheel의 동작과 for문의 실행을 분리하므로 부하가 걸리지 않음

 

이벤트 위임
비슷한 패턴의 여러 요소에서 이벤트를 핸들링하는 경우
단일 조상 요소에서 제어하는 이벤트 위임 패턴을 사용할 수 있다.

조상 요소에 이벤트를 위임하는 경우는 parent 내에서 child클래스 본인을 포함해 가장 가까운 조상요소를 closest로 찾은 후 값이 null이 아니라면 child의 텍스트를 호출하므로 몇개의 요소라도 호출할 수 있다.

const parentEl = document.querySelector(".parent");
const childEls = document.querySelectorAll(".child");

//모든 대상 요소에 이벤트 등록
childEls.forEach((el) => {
  el.addEventListener("click", (event) => {
    console.log(event.target.textContent);
  });
});

//조상 요소에 이벤트 위임
parentEl.addEventListener("click", (event) => {
  const childEl = event.target.closest(".child");
  if (childEl) {
    console.log(childEl.textContent);
  }
});
반응형