캡처링과 버블링을 활용하면 강력한 이벤트 핸들링 패턴인 이벤트 위임(event delegation)을 구현할 수 있다.
유사한 내용의 핸들러를 여러개의 요소노드마다 할당하는 것은 중복개념이므로 피할 수 있다면 피하는 것이 유지보수에 좋다.
상위요소에만 핸들러를 할당하여 하위요소들의 이벤트를 처리할 수 있다면 효율적이고 이러한 것을 이벤트위임이라 한다.
이벤트위임은 이벤트가 발생했을때 상위요소핸들러에서 event.target에 접근할 수 있기때문에 가능하다.
활용
div내에 저장하기, 불러오기, 검색하기 버튼이 있을때 보통 각각의 버튼에 핸들러를 할당하여 처리할 것이다.
이벤트위임을 알면 코드가 간결해지고 유지보수가 쉬워진다.
div에 클릭이벤트를 할당하고 event.target을 구분하여 처리한다.
let menu = document.querySelector("div");
menu?.addEventListener("click", fn);
function fn(event) {
switch (event.target.dataset.action) {
case "save":
break;
case "load":
break;
case "search":
break;
}
}
핸들러내에서 action을 switch문법으로 구분해서 처리가능하나 코드가 길어져 가독성이 떨어진다.
보다 진보된 방법이 필요하다.
class Menu{
#menu;
constructor(div){
this.#menu = div;
div.addEventListener('click', this.onclick.bind(this));
}
onclick(event){
this[event.target.dataset.action](event);
}
save(event){
console.log(event.target);
}
load(event){
console.log(event.target);
}
search(event){
console.log(event.target);
}
}
new Menu(window['menu']);
핸들러를 class화하여 각 버튼의 핸들러를 객체메소드로 가지는 핸들러객체를 생성하면 가독성이 향상된다.
div.addEventListener('click', this.onclick.bind(this));로 div의 클릭이벤트를 핸들러객체의 클릭메소드로 할당할때 this를 바인딩하지 않으면 객체핸들러내의 this가 div가 되기때문에 바인딩해야 한다.
이 방법을 사용하면 버튼이 추가되어도 핸들러객체의 메소드만 추가하면 되므로 유연성이 좋아진다.
행동패턴
<input type="button" value="1" data-counter>
<input type="button" value="2" data-counter>
document.addEventListener('click', function(event) {
if (event.target.dataset.counter != undefined) { // 속성이 존재할 경우
event.target.value++;
}
});
이벤트가 발생해야할 요소노드들에 커스텀속성을 넣은후 상위요소에 핸들러를 할당한후 이벤트가 발생할때마다 event.target.dataset.counter프로퍼티값을 검사하여 처리한다.
document객체에 핸들러를 할당할 때는 document.onclick를 사용해선 안된다. 충돌가능성때문에 반드시 document.addEventListener메소드를 사용하는것이 안전하다.
토글러보여주기
<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>
여러개의 버튼들로 컨텐츠를 보여주고 숨길때 버튼마다 이벤트를 할당하지 않고 버튼에 커스텀속성을 추가하고 상위요소에서 이벤트처리시 커스텀속성값으로 처리하는것이 좋다.