이벤트 위임 (Event Delegation)
이벤트 위임이란 동적으로 하위 노드를 생성하고 삭제할 때,
상위 노드가 하위 노드들의 이벤트를 직접 탐지하고 관리하는, 디자인 패턴 중 위임 패턴을 뜻한다.
같은 이벤트를 노드 개수만큼 걸어주는 대신, 상위 노드에게 이벤트를 걸어주는 것이다.
이해가 안될 수도 있어 예제를 준비했다.
이벤트 버블링이나 캡처링을 알고 이벤트 위임을 공부하는 것이 맞지만, 일단 실전부터 해보자.
코드 예제
<div class='parent'>
</div>
<script>
const parent = document.querySelector('.parent');
for (let i=0; i<1000; i++) {
parent.innerHTML += `
<button class="child">하이</button>
<br>`;
}
</script>
위의 예제처럼 parent라는 div에 child를 1000개 만들었다고 해보자.
child 버튼에 이벤트를 걸어주고 싶다면 class 선택자를 이용해서 반복문으로 1000개의 요소에 이벤트를 생성해주면 된다.
javascript 실행 이후
<div class='parent'>
<button class='child'></button>
<button class='child'></button>
<button class='child'></button>
<!-- ...생략... -->
</div>
button이 1000개가 있다면 이벤트 또한 1000개가 마운트되는것이다.
그렇다. 무려 이벤트를 1000개나 생성한다.
너무 비효율적이다.
이런식으로 번거로운 작업을 피하고 싶을 때 이벤트 위임을 사용하면 좋다.
이벤트 위임 예제
구현 방식은 간단하다.
클릭한 영역이 어느 부분인지를 부모 노드에서 감지하면 된다.
const parent = document.querySelector('.parent');
parent.addEventListener('click', (event) => {
if (event.target.classList.contains('child')) {
alert('child 감지');
} else {
alert('child가 아님!')
}
});
위의 코드는 click을 감지한 노드가 'child'라는 클래스를 가지고 있는지 확인한 것이다.
이로써 특정 이벤트를 1000번이나 만들지 않아도 이 이벤트 하나로 처리할 수 있게 되었다.
결과물을 한번 확인해보자.
구현 결과
버튼을 1000개...가 아닌 5개만 구현해보였다.
버튼과 버튼 외의 영역 두군데에서 alert이 뜰 것이다.
두 영역을 직접 클릭해서 테스트해보자!!
구현 코드
<div class='parent' style="outline: 1px solid black;"></div>
<script>
const parent = document.querySelector('.parent');
for (let i=0; i<5; i++) {
parent.innerHTML += `
<button class="child" style="outline: 1px solid black;">나는 버튼입니다. 제발 눌러주세요.</button>
<br><br>
`
}
parent.addEventListener('click', (event) => {
if (event.target.classList.contains('child')) {
alert('눌러주셔서 감사합니다~~');
} else {
alert('난 버튼이 아니야...ㅠ')
}
});
</script>
주의점
이벤트 위임으로 이벤트를 발생시킬 요소 안에 다른 요소가 중첩되어 있다면
내부의 다른 요소를 클릭하면 우리가 원하는대로 이벤트가 발생하지 않는다.
이벤트 위임은 가능하면 단일 요소에서 사용하는 것이 좋고,
그래도 사용하고 싶다면 내부요소까지 같은 className을 추가해주어야 한다.
만약에 중첩된 요소를 제외한 나머지 영역만 이벤트를 실행하고 싶다면 위에서 설명한대로 하면 된다.
후기
같은 이벤트를 수십, 수백번 할당해 주기보다는
이런식으로 이벤트를 단 하나만 이용하여 관리하는 것이 더 효율적이라는 생각이 든다.
이번 과제를 통해 재밌는것을 많이 배웠다.
단순히 배우는 것에 그치지 않고, 내 것으로 만들었다는 생각이 들어 뿌듯하다 :)
'Language > JavaScript' 카테고리의 다른 글
[Javascript] 전개연산자(spread operator) 사용 시 얕은 복사가 발생하는 경우 (0) | 2021.11.08 |
---|---|
[Node.js] replaceAll() is not a function (0) | 2021.11.03 |
[Vue] router-link 에서 click이벤트 사용법 (0) | 2021.10.27 |
[Javascript] Web Storage (0) | 2021.10.07 |
ES6 문법 (0) | 2021.07.04 |