
제로베이스 자바스크립트 기초개념 이벤트(Event) 부분 정리
축약된 부분이 존재할 수 있습니다.
화면에서 발생할 수 있는 다양한 상황
대상에서 청취(Listen)할 이벤트 종류와 이벤트가 발생하였을 때 호출할 콜백(Handler)을 등록한다.
const parentEl = document.querySelector(".parent");
const childEl = document.querySelector(".child");
parentEl.addEventListener("click", () => {
console.log("부모");
});
childeEl.addEventListener("click", () => {
console.log("자식");
});
// 이벤트 버블링 발생
대상에게 등록했던 이벤트 핸들러를 제거합니다.
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> 태그에서 페이지 이동 방지!
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("모든 값이 초기화되었습니다.");
});