유튜브 코딩앙마 영상을 보고 정리한 내용입니다.
이벤트가 어떻게 전파되는지 알아봅니다.
//html
<div id="box">
<ul id="list">
<li id="color">Red</li>
</ul>
</div>
이런 구조일 때 모든 요소를 클릭할 때 콘솔로그가 찍히게 한다면,
const box = document.getElementById("box");
const list = document.getElementById("list");
const color = document.getElementById("color");
document.body.addEventListener('click', ()=>{
console.log('1. body')
})
box.addEventListener('click', ()=>{
console.log('2. div')
})
list.addEventListener('click', ()=>{
console.log('3. ul')
})
color.addEventListener('click', ()=>{
console.log('4. li')
})
// 이렇게 하고 li 요소를 클릭하면 콘솔창에 이렇게 찍힙니다.
4/ li
3/ ul
2/ div
1/ body
자식요소를 클릭하면 부모요소들도 순차적으로 클릭됩니다. 하위 요소에서 상위 요소로 올라가는데, 이것을 이벤트 버블링(bubbling) 이라고 부릅니다. 대부분 전파되지만 fucus
blur
mouseenter
mouseleave
는 버블링이 안됩니다. 이럴 때는 이런 이벤트로 대체해주면 됩니다. focusin
focusout
mouseover
mouseout
이벤트 버블링은 임의적으로 막을 수 있습니다. (막아야 할 경우가 거의 없긴 함)
text.addEventListener("focusout", () => {
event.stopPropagation();
})
부모요소에서 이벤트를 위임할 수도 있습니다.
//html
<ul id="list">
<li></li>
<li></li>
<li></li>
</ul>
//script
const list = document.getElementById("list");
const colors = list.children;
function clickHandler(event) {
for (c of colors) {
c.classList.remove("on"); // 모든 li 의 on 클래스 제거
}
event.target.classList.add("on"); // 클릭한 요소에 on 클래스 추가
}
document.getElementById("list").addEventListener("click", clickHandler);
li
를 클릭하지 않고 부모인 ul
에게 위임해서 하나의 클릭 이벤트만 만들어도 됩니다. 버블링 때문에 가능합니다.
//html
<ul id="list">
<li><a href="#">test</a></li>
<li><a href="#">test</a></li>
<li><a href="#">test</a></li>
</ul>
이렇게 li
태그 안에 자식요소로 a
가 생겼을 경우. a
태그를 눌러도 li
가 선택되게 하려면 아래와 같이 수정합니다. target
은 실제 이벤트를 발생시키는 요소 li
a
이고, currentTarget
은 이벤트 핸들러가 등록된 요소 ul
입니다. a
를 눌러도 li
의 클래스가 추가되도록 수정한다면
function clickHandler(event) {
let target = event.target;
if (target.tagName === "A") { // 태그가 a 면
target = target.parentElement; // 타겟에 타겟의 부모요소를 넣어주고
}
for (c of colors) {
c.classList.remove("on");
}
event.target.classList.add("on"); // 부모요소에게 클래스 추가
}
ul
태그를 선택해서 의도하지 않은 동작이 일어난다면, 아래처럼 수정하면 됩니다.
function clickHandler(event) {
let target - event.target;
if (target.tagName === "A") { // 태그가 a 면
target = target.parentElement; // 타겟에 타겟의 부모요소를 넣어주고
} else if (target === event.currentTarget) {
return;
}
for (c of colors) {
c.classList.remove("on");
}
event.target.classList.add("on"); // 부모요소에게 클래스 추가
}