Javascript - 이벤트 위임
이번 블로그 주제는 자바스크립트의 이벤트 버블링/캡처링과 연결되는 이벤트 위임 개념이다. 버블링/캡처링 개념에 대해서는 저번에 작성한 블로그를 참고해주세요! https://no2jfamily.tistory.com/110
Javascript - 이벤트 버블링/캡처링
첫 기업 과제테스트를 하면서 중요성을 느낀 바닐라 JS의 주요개념 이벤트 버블링/캡처링에 대해서 정리하고자 한다 ㅎㅎ 오랜만에 작성하는 블로그 인 만큼 재미있게 정리해보자. 물론 과제 테
no2jfamily.tistory.com
<참고 레퍼런스>
https://ko.javascript.info/event-delegation
이벤트 위임
ko.javascript.info
<이벤트 위임>
개념: 이벤트 위임은 공통 부모가 있는 자식 요소가 있는 경우 이벤트 헨들러를 공통 부모요소 에만 적용 함으로써 부모에게만 이벤트를 위임하는 방법이다. 쉽게 말하면 자식 요소 하나하나에 이벤트 이벤트 헨들러를 할당하는 것이 아닌 공통 부모 요소에 하나만 할당하는 것을 의미한다.
그래서 이벤트 위임의 장단점을 정리하면 다음과 같다.
장점 중 첫 번째 장점같은 경우 addEventListener라는 훅을 여러 번 사용한다면 메모리 측면에서 비 효율적이고 성능이 떨어지기 때문에 이벤트 위임을 적용하면 해당 장점을 누릴 수 있다.
이벤트 위임의 사용예시를 보면 더욱 쉽게 이해가 갈 것인데 예시는 다음과 같다.
<table>
<tr>
<th colspan="3"><em>Bagua</em> Chart: Direction, Element, Color, Meaning</th>
</tr>
<tr>
<td class="nw"><strong>Northwest</strong><br>Metal<br>Silver<br>Elders</td>
<td class="n">...</td>
<td class="ne">...</td>
</tr>
<tr>...2 more lines of this kind...</tr>
<tr>...2 more lines of this kind...</tr>
</table>
3 * 3 으로 이루어진 테이블이 존재한다고 가정해보자. 여기서 <td>가 여러개 있는 것을 볼 수 있는데 각 <td>마다 이벤트 헨들러를 할당하는게 아니라 <table> 요소에 이벤트 헨들러를 할당한다. 이게 바로 이벤트 위임이다.
event.target을 통해 어디서 클릭이 발생했는지를 발견한 다음 target 변수에 담는다. 그리고 <td>에서 클릭이 발생했다면 highlight 함수를 호출하며 클릭된 <td>가 강조되도록 구현한다.
let selectedTd;
table.onclick = function(event) {
let target = event.target; // 클릭이 어디서 발생했을까요?
if (target.tagName != 'TD') return; // TD에서 발생한 게 아니라면 아무 작업도 하지 않습니다,
highlight(target); // 강조 함
};
function highlight(td) {
if (selectedTd) { // 이미 강조되어있는 칸이 있다면 원상태로 바꿔줌
selectedTd.classList.remove('highlight');
}
selectedTd = td;
selectedTd.classList.add('highlight'); // 새로운 td를 강조 함
}
근데 여기서 확인해야할건 다시 위에 있는 HTML 구조를 확인해보자. 그럼 <td>태그 안에 <strong>태그가 있는 것을 볼 수 있는데 만약 <strong>태그를 클릭하게 되면 어떻게 될까? 이때는 <td>안쪽에서 일어난 클릭인지 아닌 클릭인지를 판단해야하고 이때 사용할 수 있는 개념이 closest 메소드이다.
table.onclick = function(event) {
let td = event.target.closest('td'); // (1)
if (!td) return; // (2)
if (!table.contains(td)) return; // (3)
highlight(td); // (4)
};
let td = event.target.closest('td') 를 보면 event.target은 클릭한 <strong>태그가 담겨있을 것이다. 이때 closest 메소드는 이벤트가 발생한 요소부터 시작해 위로 올라가며 가장 가까운 <td>요소를 찾아준다.(연관: 이벤트 버블링) 이처럼 해당 코드를 통해서 기존에 <td>를 기준으로 어디서 클릭이 발생했는지 파악하기 어려웠던 단점을 해소할 수 있다.
<이벤트 위임과 행동패턴>
이벤트 위임은 요소에 선언적 방식으로 '행동(behavior)'을 추가할 때 사용할 수도 있다. 모던 자바스크립트 튜토리얼에는 data-counter, data-toggle-id 라는 두 가지 행동패턴을 이용한 예시들이 존재한다.
행동패턴을 이용하여 구현하면 자바스크립트 로직을 통해 해당 기능들을 구현하지 않기 때문에 매우 편리한 장점이 있다.
적용하는 방법은 다음과 같다.
1. 요소의 행동을 설명하는 커스텀 속성(data-counter, data-toggle-id)을 요소에 추가한다.
2. 문서 전체를 감지하는 핸들러(document 객체에 addEventListener 이벤트헨들러 설정)가 이벤트를 추적하게 한다. 1에서 추가한 속성이 있는 요소에서 이벤트가 발생하면 작업을 수행한다.
<data-counter 예시>
첫 번째 카운터: <input type="button" value="1" data-counter>
두 번째 카운터: <input type="button" value="2" data-counter>
<script>
document.addEventListener('click', function(event) {
if (event.target.dataset.counter != undefined) { // 속성이 존재할 경우
event.target.value++;
}
});
</script>
<data-toggle-id 예시>
<button data-toggle-id="subscribe-mail">
구독 폼 보여주기
</button>
<form id="subscribe-mail" hidden>
메일 주소: <input type="email">
</form>
<script>
document.addEventListener('click', function(event) {
let id = event.target.dataset.toggleId;
if (!id) return;
let elem = document.getElementById(id);
elem.hidden = !elem.hidden;
});
</script>