이벤트 위임은 이벤트 리스너를 자식 요소 대신 부모 요소에 추가하는 기법
부모 요소에 단일 핸들러만 필요하기 때문에 메모리 사용 공간 감소
요소의 추가 삭제시 별도로 이벤트를 바인딩하고 해제할 필요 없음
이벤트 위임을 사용하기 위해서는 이벤트 버블링이 필요
<ul>
<li>리스트 1</li>
<li>리스트 2</li>
<li>리스트 3</li>
</ul>
<button type="button">추가</button>
const list = document.querySelector("ul");
const listItems = document.querySelectorAll("li");
// before - 새로운 아이템에 대한 핸들러가 정상적으로 동작하지 않음
listItems.forEach((item) => {
item.addEventListner("click", (event) => {
console.log(e.target.innerText);
});
})
// after - 새로운 아이템에도 이벤트 핸들러가 정상적으로 동작
list.addEventListner("click", (event) => {
if(e.target.tagName === "LI") {
console.log(e.target.innerText);
}
});
document.querySelector("button").addEventListner("click", (event) => {
const newItem = document.createElement("li");
newItem.innerText = "새 리스트";
list.appendChild(newItem);
})
특정 자식 요소에 이벤트가 발생하면 부모 요소에게까지 이벤트가 전달되는 현상
<div>
div
<p>
p
<span>span</span>
</p>
</div>
const $span = document.querySelector("span");
const $p = document.querySelector("p");
const $div = document.querySelector("div");
const log = (message) => {
console.log(message);
}
$span.addEventListener("click", () => log("click span"));
$p.addEventListener("click", () => log("click p"));
$div.addEventListener("click", () => log("click div"));
<span>
을 클릭하면 console.log
에 아래와 같이 자식 요소 이벤트 부터 부모 요소순으로 log 찍힘 (자식 -> 부모)
click span
click p
click div
이처럼 자식 요소 span 에서 이벤트가 발생하면 해당 이벤트가 부모 요소 p, div에 전달되는 현상을 이벤트 버블링이라고 한다
이벤트 버블링은 최종적으로 <html>
엘리먼트까지 전달되며, 이 이벤트를 막기 위해서는 event.stopPropagation()
을 추가하고, 여러 이벤트 핸들러가 있을 경우 event.stopImmediatePropagation()
을 사용하면 된다
이벤트 캡쳐링은 특정 요소에서 이벤트가 발생 했을 경우, 이벤트의 최상단 부모 요소에서부터 전달되어 내려오는 현상
캡쳐링을 수행하기 위해서는 이벤트 핸들러에 { capture : true }
혹은 true
로 옵션 설정을 해야한다 ( default 는 false
)
<div>
div
<p>
p
<span>span</span>
</p>
</div>
const $span = document.querySelector("span");
const $p = document.querySelector("p");
const $div = document.querySelector("div");
const log = (message) => {
console.log(message);
}
$span.addEventListener("click", () => log("click span"), true);
$p.addEventListener("click", () => log("click p"), true);
$div.addEventListener("click", () => log("click div"), true);
<span>
을 클릭하면 console.log
에 부모 요소의 이벤트 부터 자식 요소순으로 log가 찍힘 (부모 -> 자식)
click div
click p
click span
이벤트 캡쳐링에서도 stopPropagation() 을 통해 이벤트 전파를 막아줄 수 있으며, 이벤트 버블링에서는 target 요소만 이벤트를 발생하게해주는데 반해, 이벤트 캡처링에서는 최상위 부모 요소에게 이벤트가 발생하도록 해준다