❗️이벤트 전파(Event Propagation)
자바스크립트에서 이벤트가 발생하면 세가지 단계를 거친다.
- 캡쳐링 단계
상위 요소 -> 하위 요소
DOM 트리의 가장 상위 요소인 document에서 이벤트가 발생한다.
document부터 하위 요소들을 타고 target 요소까지 내려온다. - target 단계
이벤트 target에 도달
이벤트가 target에 도착하면, 콜백 함수를 통해 이벤트를 처리한다. - 버블링 단계
하위 요소 -> 상위 요소
다시 이벤트가 target부터 상위 요소들을 타고 document까지 올라간다.
캡쳐링 단계와 동일하게 모든 부모 요소를 지나간다.
한 줄 요약하자면!
이벤트 캡쳐링 : 가장 상위 요소에서 이벤트가 발생한 타겟 요소까지 내려가는 것이다.
이벤트 버블링 : 타겟 요소에서 이벤트가 발생했을 때, 해당 이벤트가 상위 요소들로 전달되는 것이다.
불필요한 이벤트 전파로 의도하지 않은 동작이 일어날 수 있다.
ex) 하위 요소만 스크롤하고 싶은데 상위 요소가 함께 스크롤 됨
event.stopPropagation();
이벤트 전파를 막고 싶다면 위의 코드를 이용하면 된다.
❗️event.target과 event.currentTarget
- event.target
실제 이벤트가 발생된 요소
즉, 내가 클릭한 요소를 의미한다.
- event.currentTarget
이벤트 핸들러가 실제로 등록된 요소
이벤트 전파를 통해 이벤트가 등록된 요소를 의미한다.
const App = () => {
const handleClickButton = (event) => {
console.log(event.target);
console.log(event.currentTarget);
};
return (
<div>
<button onClick={handleClickButton}>
<span>Heedonguri</span>
</button>
</div>
);
};
export default App;
버튼 태그 하위에 span 태그가 있고 클릭 핸들러는 버튼에 등록되어있다.
이때, span 태그인 Heedonguri를 누른다면 콘솔 창에는 다음과 같이 출력된다.
event.target은 span 태그를 반환하고,
event.currentTarget은 버튼 태그를 반환한다.
❗️이벤트 위임(Event Delegation)
이벤트 위임이란 상위 요소에서 하위 요소 이벤트를 제어하는 것이다.
하위 요소에 모두 이벤트 핸들러를 각각 등록하는 대신에, 부모 요소에 이벤트 핸들러를 등록한다.
이벤트 리스너를 많이 등록하게 되면 메모리 점유율이 늘어나서 페이지 성능 저하를 일으킨다.
또한 요소가 추가됨에 따라, 이벤트 핸들러도 매번 등록해줘야하므로 유지 보수가 어려워진다.
이러한 문제를 해결하는 방법이 이벤트 위임이다.
이벤트 전파에서 봤듯이, 이벤트가 상위 요소로 전달되는 이벤트 버블링이 일어난다.
상위 요소에 이벤트 등록을 위임하면 하위 요소에 이벤트 핸들러를 매번 등록하지 않아도 된다.
<html>
<body>
<div class="menu">
<button class="btns">
<span>첫번째</span>
</button>
<button class="btns">
<span>두번째</span>
</button>
<button class="btns">
<span>세번째</span>
</button>
</div>
<script>
for (const item of document.querySelectorAll(".btns")) {
item.addEventListener("click", (event) => {
console.log(event.target);
});
}
</script>
</body>
</html>
위의 코드는 각 버튼에 이벤트 핸들러를 작성한 코드이다.
이렇게 작성해도 코드는 잘 동작하지만, 만약 버튼이 추가된다면?
추가되는 버튼마다 이벤트 핸들러를 등록해줘야 한다.
따라서 이벤트를 버튼의 상위 요소인 <div class="menu">에서 처리하도록 해보자.
<html>
<body>
<div class="menu">
<button class="btns">
<span>첫번째</span>
</button>
<button class="btns">
<span>두번째</span>
</button>
<button class="btns">
<span>세번째</span>
</button>
</div>
<script>
document.querySelector(".menu").addEventListener("click", (event) => {
console.log(event.target);
});
</script>
</body>
</html>
이벤트 핸들러를 menu에 등록함으로써 이벤트 위임을 했다.
하지만 위의 코드는 div 태그 전체에 이벤트를 등록해서, 버튼들 사이의 빈 공간을 클릭해도 이벤트가 발생한다.
document.querySelector(".menu").addEventListener("click", (event) => {
if (!event.target.classList.contains("btns")) {
return;
}
console.log(event.target);
});
클릭된 요소가 btns 클래스를 가지는 지 확인해줌으로써 해결되었다.
❗️React의 이벤트 위임
React에서는 애초에 모든 이벤트가 이벤트 위임으로 처리된다.
on~로 붙여주는 모든 이벤트 핸들러들이 해당 요소에 붙여지는게 아니라,최상위 요소인 document에 붙여져서 모든 이벤트를 처리한다. -> 이건 react 17 이전 버전에 해당
root 요소에 붙여저서 모든 이벤트를 처리한다. -> react 17 부터
root에서 모든 이벤트를 감시하는 것이다.
vue도 같은지 궁금해서 찾아보고 싶었는데,, 자료가 안나온다,,
'WEB' 카테고리의 다른 글
[WEB] SEO 최적화 (0) | 2024.08.20 |
---|---|
[WEB] webpack vs vite (0) | 2024.08.14 |
[WEB] 웹 레이아웃 (0) | 2024.07.31 |
[CSS] Border vs Outline (0) | 2024.07.31 |
[WEB] 브라우저 렌더링 과정 (0) | 2024.07.03 |