[ JS ] - 이벤트

200원짜리개발자·2024년 6월 13일
0

FrontEnd

목록 보기
23/29
post-thumbnail

제로베이스 자바스크립트 기초개념 이벤트(Event) 부분 정리
축약된 부분이 존재할 수 있습니다.

이벤트

화면에서 발생할 수 있는 다양한 상황

이벤트 추가 및 제거

대상.addEventListener(이벤트 종류, 핸들러)

대상에서 청취(Listen)할 이벤트 종류와 이벤트가 발생하였을 때 호출할 콜백(Handler)을 등록한다.

const parentEl = document.querySelector(".parent");
const childEl = document.querySelector(".child");
  
parentEl.addEventListener("click", () => {
  console.log("부모");
});
  
childeEl.addEventListener("click", () => {
  console.log("자식");
});
  
// 이벤트 버블링 발생

대상.removeEventListener(이벤트 종류, 핸들러)

대상에게 등록했던 이벤트 핸들러를 제거합니다.

const parentEl = document.querySelector(".parent");
const childEl = document.querySelector(".child");
  
// 삭제하기 위해서는 기명함수가 필요하다.
const handler = () => {
  console.log("부모");
};
  
parentEl.addEventListener("click", handler);
childEl.addEventListener("click", () => {
  parentEl.removeEventListener("click", handler);
});

이벤트 객체

.addEventListener() 핸들러의 첫 매개변수로, 발생한 이벤트의 정보를 가진 객체를 전달합니다.

const parentEl = document.querySelector(".parent");
  
parentEl.addEventListener("click", (event) => {
  console.log(parentEl);
  console.log(event.target);
});
  
const inputEl = document.querySelector("input");
inputEl.addEventListener("keydown", (event) => {
  console.log(event.key);
  console.log(inputEl.value);
  console.log(event.target.value);
});

이벤트 기본 동작 방지

event.preventDefault()

  • 이벤트의 기본 동작을 방지합니다.
    이벤트의 기본 동작이란 a태그에서 href에 적힌 링크로 이동하는 것이 기본 동작이라고 볼 수 있다.
// <a> 태그에서 페이지 이동 방지!
const anchorEl = document.querySelector("a");
anchorEl.addEventListener("click", (e) => {
  e.preventDefault();
});
  
// 마우스의 휠의 스크롤 동작 방지!
const parentEl = document.querySelector(".parent");
parentEl.addEventListener("wheel", (e) => {
  e.preventDefault();
});

이벤트 버블링

const parentEl = document.querySelector(".parent");
const childEl = document.querySelector(".child");
const anchorEl = document.querySelector("a");
  
window.addEventListener("click", () => {
  console.log("윈도우");
});
document.documentElement.addEventListener("click", () => {
  console.log("HTML");
});
document.body.addEventListener("click", () => {
  console.log("body");
});
parentEl.addEventListener("click", (e) => {
  console.log("parent");
  // e.stopPropagation(); // 버블링 정지!
});
childEl.addEventListener("click", () => {
  console.log("child");
});
anchorEl.addEventListener("click", () => {
  console.log("a");
});

이러한 코드가 있다고 하였을 때, a 요소를 클릭했다고 해보자.
그러면 a 요소의 상위 요소들의 같은 이벤트들은 전부 발생할 것이다.

이런식으로 하위 요소의 이벤트를 발생하였을 때, 같은 이벤트의 상위 요소의 이벤트도 발생되는 현상을 이벤트 버블링이라고 한다.

이를 멈추게 하기 위해서는 event.stopPropagation() 을 사용 해야한다.

이벤트 캡처링

const parentEl = document.querySelector(".parent");
const childEl = document.querySelector(".child");
const anchorEl = document.querySelector("a");
  
window.addEventListener("click", () => {
  console.log("윈도우");
});
document.documentElement.addEventListener("click", () => {
  console.log("HTML");
});
document.body.addEventListener("click", () => {
  console.log("body");
});
parentEl.addEventListener("click", (e) => {
  console.log("parent");
  // e.stopPropagation(); // 버블링 정지!
});
childEl.addEventListener("click", () => {
  console.log("child");
});
anchorEl.addEventListener("click", (e) => {
  e.preventDefault();
  console.log("a");
});

이러한 코드가 있다고 해보자.

a > c > p > b > h > w 순서대로 이벤트 버블링이 발생하여 차례차례 이벤트가 발생할 것이다.
그런데 여기서 a보다 body요소가 먼저 이벤트가 발생되면 좋겠다라고 생각한다면, 우리가 아직 몰랐던 addEventListener의 3번째 인수를 사용할 수 있다.

document.body.addEventListener(
  "click",
  () => {
    console.log("body");
  },
  { capture: true },
);

이런식으로 객체의 형태로 capture: true를 해준다면 a요소를 클릭하고 이벤트 버블링을 확인한 후에 capture가 되어있는 요소의 이벤트를 가장 먼저 발생시킨다.
또한 capture는 capture되어는 요소 중에 더 상위요소를 먼저 발생시킨다.

한글 입력 이벤트 중복

브라우저 입력기(IME)의 CJK(중국어, 일본어, 한국어) 문자 구성 중에는 이벤트 핸들러가 2번 실행될 수 있습니다.

const inputEl = document.querySelector("input");
inputEl.addEventListener("keydown", (e) => {
  // e.isComposing - 한글 입력 중인지 여부를 확인합니다.
  // if (e.isComposing) return;
  if (e.key === "Enter") {
    const h1El = document.createElement("h1");
    h1El.textContent = inputEl.value;
    document.body.append(h1El);
  }
});

그래서 이러한 코드가 실행되었을 때, h1이 두 개가 만들어질 수도 있다.
그럴 떄, e.isComposing을 사용해서 CJK 문자 구성 중에서는 return 시키면 해결이 된다.

마우스와 포인터 이벤트

포인터 이벤트는 마우스 이벤트의 하위 이벤트이다. (사실상 둘이 같다고 봐야됨)

const parentEl = document.querySelector(".parent");
const childEls = document.querySelectorAll(".child");
  
childEls.forEach((childEl) => {
  // click - 클릭했을 때,
  // dblclick - 더블 클릭했을 때
  childEl.addEventListener("click", () => {
    childEl.classList.toggle("active");
  });
  
  // contextmenu - 우클릭 했을 때
  childEl.addEventListener("contextmenu", (e) => {
    e.preventDefault();
    console.log(childEl.textContent);
  });
});
  
// mousedown - 버튼을 누를 때
// mouseup - 버튼을 땔 때
// mouseenter - 포인터가 요소로 들어갈 때
// mouseleave - 포인터가 요소에서 나올 때
parentEl.addEventListener("mousedown", () => {
  parentEl.classList.add("active");
});
parentEl.addEventListener("mouseup", () => {
  parentEl.classList.remove("active");
});
  
// mousemove - 포인터가 움직일 때
parentEl.addEventListener("mousemove", (e) => {
  // console.log(e.x, e.y);
});
  
parentEl.addEventListener("wheel", (e) => {
  // console.log("Parent Wheel");
});

키보드 이벤트

const inputEl = document.querySelector("input");
  
// keydown - 키를 누를 때
// keyup - 키를 땔 때
inputEl.addEventListener("keydown", (e) => {
  console.log(e.key);
  if (e.key === "Enter") {
    console.log("엔터");
  }
  if (e.key === "Escape") {
    console.log("ESC");
  }
  if (e.key === " ") {
    console.log("스페이스");
  }
});

keypress같은 경우에는 Deprecated되어서 더 이상 사용하지 않는다.

양식과 포커스이벤트

양식(form)에서 사용하는 이벤트에 대해 알아보자.

const formEl = document.querySelector("#login");
const inputEls = document.querySelectorAll("input");
  
inputEls.forEach((el) => {
  // focus(focusin) - 요소가 포커스를 얻었을 때
  el.addEventListener("focus", () => {
    formEl.classList.add("active");
  });
  // blur(focusout) - 요소가 포커스를 잃었을 때
  el.addEventListener("blur", () => {
    formEl.classList.remove("active");
  });
  // input - 값이 변경되었을 때
  // change - 상태가 변경되었을 때
  el.addEventListener("input", (e) => {
    console.log(e.target.value);
  });
});
  
// submit - 제출 버튼을 선택했을 때
formEl.addEventListener("submit", (e) => {
  e.preventDefault();
  const data = {
    id: e.target[0].value,
    pw: e.target[1].value,
  };
  // fetch(https://....)
  console.log("서버로 제출했습니다.");
});
  
// reset - 리셋 버튼을 선택했을 때
formEl.addEventListener("reset", () => {
  console.log("모든 값이 초기화되었습니다.");
});
profile
고3, 프론트엔드

0개의 댓글