이벤트 캡처링과 버블링 그리고 위임
19108 단어 JavaScriptJavaScript
이벤트
- 이벤트(event)란 웹 브라우저가 알려주는 HTML 요소에 대한 사건의 발생을 의미한다.
- 웹 페이지에 사용된 자바스크립트는 이렇게 발생한 이벤트에 반응하여 특정 동작을 수행할 수 있다.
이벤트 핸들러
- 이벤트에 반응하려면 이벤트가 발생했을 때 실행되는 함수인 핸들러(handler)를 할당해야 한다.
- 핸들러는 사용자의 행동에 어떻게 반응할지를 자바스크립트 코드로 표현한 것입니다.
- addEventListener() 메소드를 사용하여 이벤트 핸들러를 등록한다.
- removeEventListener() 메소드를 사용하여 이벤트 핸들러를 삭제한다.
이벤트 버블링
- 한 요소에 이벤트가 발생하면, 이 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 존재한다면 동작한다. 가장 최상단의 조상 요소를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작한다.
const outer = document.querySelector('.outer');
const middle = document.querySelector('.middle');
const button = document.querySelector('button');
outer.addEventListener('click', (e) => {
console.log(`${e.currentTarget}, ${e.target}`);
});
middle.addEventListener('click', (e) => {
console.log(`${e.currentTarget}, ${e.target}`);
});
button.addEventListener('click', (e) => {
console.log(`${e.currentTarget}, ${e.target}`);
});
- 위 코드에서 부모 자식 순서는 outer > middle > button 이고 로그의 출력순서는 button, middle, outer순으로 버블링이 이루어지는 것을 볼 수 있다.
이벤트 버블링 중단하기
- 핸들러에게 이벤트를 완전히 처리하고 난 후 버블링을 중단하도록 명령할 수도 있다.
- 이벤트 객체의 메서드인 event.stopPropagation()과 event.stopImmediatePropagation()를 사용한다.
event.stopPropagation()
위쪽으로 일어나는 버블링은 막아주지만, 같은 요소에 핸들러가 여러개가 존재한다면 다른 핸들러들의 동작을 막지 못한다.
event.stopImmediatePropagation()
같은 요소의 특정 이벤트에서 메소드를 실행한 핸들러만 동작하고 나머지 핸들러 모두가 동작하지 않는다. - 버블링을 꼭 멈춰야 하는 명백한 상황이 아니라면 버블링을 막지말고, 아키텍처를 잘 고려해 진짜 막아야 하는 상황에서만 버블링을 막아야 한다.
const outer = document.querySelector('.outer');
const middle = document.querySelector('.middle');
const button = document.querySelector('button');
outer.addEventListener('click', (e) => {
// 메소들을 사용한 버블링 막기보다 안정적인 방법
// 이벤트가 발생한 타겟과 현재 핸들러가 동작하는 타겟이 같은 경우가 아니면 아무동작없이 return
if (e.currentTarget !== e.target) {
return;
}
console.log(`${e.currentTarget}, ${e.target}`);
});
middle.addEventListener('click', (e) => {
// 메소들을 사용한 버블링 막기보다 안정적인 방법
// 이벤트가 발생한 타겟과 현재 핸들러가 동작하는 타겟이 같은 경우가 아니면 아무동작없이 return
if (e.currentTarget !== e.target) {
return;
}
console.log(`${e.currentTarget}, ${e.target}`);
});
button.addEventListener('click', (e) => {
console.log(`${e.currentTarget}, ${e.target}`);
});
이벤트 캡처링
- 이벤트 흐름엔 3가지 단계가 존재한다.
- 캡처링 단계 : 이벤트가 하위 요소로 전파되는 단계
- 타깃 단계 : 이벤트가 실제 타깃 요소에 전달되는 단계
- 버블링 단계 : 이벤트가 상위 요소로 전파되는 단계
- 위 그림은 td를 클릭하면 이벤트가 최상위 조상에서 시작해 아래로 전파되고(캡처링 단계), 이벤트가 타깃 요소에 도착해 실행된 후(타깃 단계), 다시 위로 전파됩니다(버블링 단계). 이런 과정을 통해 요소에 할당된 이벤트 핸들러가 호출됩니다.
- 캡처링 단계를 이용해야 하는 경우는 흔치 않기 때문에, 버블링 단계에서의 로직 처리가 더 자주 사용된다.
이벤트 위임
- 이벤트 위임은 비슷한 방식으로 여러 요소를 다뤄야 할 때 사용한다.
- 이벤트 위임을 사용하면 요소마다 핸들러를 할당하지 않고, 요소의 공통 조상에 이벤트 핸들러를 단 하나만 할당해도 여러 요소를 한꺼번에 다룰 수 있습니다.
// Bad Code
// 모든 자식요소에 이벤트리스너를 등록하여 메모리 낭비
const lis = document.querySelectorAll('li');
lis.forEach((el) => {
el.addEventListener('click', () => {
el.classList.add('selected');
});
});
// Good Code
// 이벤트 위임을 통한 강력한 핸들링
const ul = document.querySelector('ul');
ul.addEventListener('click', (e) => {
// e.target을 통해 이벤트가 발생한 요소를 알 수 있다.
if (e.target.tagName === 'LI') {
e.target.classList.add('selected');
}
});
참고자료
- https://ko.javascript.info/introduction-browser-events
- https://ko.javascript.info/bubbling-and-capturing
- https://ko.javascript.info/event-delegation
- https://velog.io/@nomadhash/Java-Script-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EB%B8%94%EB%A7%81%EA%B3%BC-%EC%BA%A1%EC%B3%90%EB%A7%81
Author And Source
이 문제에 관하여(이벤트 캡처링과 버블링 그리고 위임), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@codenmh0822/이벤트-캡처링과-버블링-그리고-위임저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)