Javascript 이벤트(추가, 삭제, 객체, 옵션, 버블링, 위임)
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);
}
});