오늘 공부한 내용은 'bubbling' 과 이를 방지? 멈추는 이벤트까지 정리해보려 한다.
bubbling
버블링을 이론적으로 딱딱하게 설명해보자면,
한 요소에서 이벤트가 발생하면 할당된 핸들러가 동작하고 그 위에 있는 부모요소의 핸들러까지 실행된다.
부모요소 뿐만 아니라 최상단에도 이벤트가 할당되어 있다면 이를 만날 때까지 반복해서 이벤트가 실행된다.
노잼이니까 수업 때 본 코드를 보도록 하자!
<section onclick="alert('section clicked!')">
<p onclick="alert('p tag clicked!')">
I am P Tag.
<button onclick="alert('button clicked!')">Click</button>
</p>
</section>
인라인 이벤트로 모든 태그에 onclick 이벤트를 부여해서 경고창이 뜨게 만들었다.
section > p > button 순으로!
이 코드의 문제점은 가장 자식요소인 button
을 클릭하게 되면
1. button
의 alert 창이 뜨고
2. p
의 alert 창이 뜨고
3. section
의 경고창까지 연달아서 뜬다.
이것이 바로 버블링이라고 한다.
이를 막기 위해서는 이벤트를 실행하고자 하는 요소를 정확하게 선택했는지 확인해야 하는데 event.target이 그 역할을 한다.
event.target
부모요소의 핸들러는 정확히 어디서 발생했는지 정보를 알 수 있다.
target
은 이벤트가 발생한 가장 안 쪽 요소이므로 event.target
를 사용하면 된다.
html
<div id="container">
Click To Hide
<button id="changeColor">Change Color</button>
</div>
위 html로 2가지 이벤트를 실행하려고 한다.
⭐️ container 안에 button이 있어 버블링이 될 수 있다는 걸 주의해야한다.
javascript
const button = document.querySelector('#changeColor');
const container = document.querySelector('#container');
button.addEventListener('click', function (e) {
container.style.backgroundColor = makeRandColor();
})
container.addEventListener('click', function () {
container.classList.toggle('hide');
})
const makeRandColor = () => {
const r = Math.floor(Math.random() * 255);
const g = Math.floor(Math.random() * 255);
const b = Math.floor(Math.random() * 255);
return `rgb(${r}, ${g}, ${b})`;
}
button
, container
를 변수로 담기button
을 클릭하면 container
의 배경 색이 랜덤으로 바뀌게 이벤트 만들기container
를 클릭하면 "display: none" 이 실행되는 hide라는 클래스를 toggle 하기makeRandColor
는 색상 rgb 값을 랜덤으로 만들어주는 함수얼핏 코드만 보면 문제없어 보이지만 앞서 본 것처럼 container 안에 button이 있어 버블링이 되어 버튼을 클릭해도 hide 된다.
이를 막기 위해서는 e.stopPropagation(); 을 작성해주어야 한다.
e.stopPropagation()
특정 이벤트를 처리하는 핸들러가 여러 개 일 때, 하나가 버블링을 멈춰도 다른 요소의 이벤트에는 영향을 미치지 않는다.
⭐️ 위쪽으로 일어나는 버블링은 막아주지만 다른 핸들러가 동작하는건 막지 못한다.
e.stopPropagation(); 를 추가한 최종 스크립트
const button = document.querySelector('#changeColor');
const container = document.querySelector('#container');
button.addEventListener('click', function (e) {
container.style.backgroundColor = makeRandColor();
e.stopPropagation(); // 버블링 stop 해줌
})
container.addEventListener('click', function () {
container.classList.toggle('hide');
})
const makeRandColor = () => {
const r = Math.floor(Math.random() * 255);
const g = Math.floor(Math.random() * 255);
const b = Math.floor(Math.random() * 255);
return `rgb(${r}, ${g}, ${b})`;
}
e.stopPropagation();
를 추가해줘서 버튼을 클릭하면 색이 바뀌고, 글씨 container를 클릭하면 사라지게 만들었다.
추가로 공부해야할 부분은 event.stopImmediatePropagation()
인데 버블링과 요소에 할당된 다른 핸들러 동작까지 모두 막을 때 사용해야한다.
❌
좋아보이지만 꼭 필요한 경우가 아닌 경우 버블링을 막지 않도록해야한다.
버블링을 막을 일은 거의 없다고 하는데 그래도 알아두면 좋을 것 같아서 정리해보았다. this를 활용하 방법도 추가해서 공부해야할 것 같다..!