이벤트 위임은 실제 바닐라 JS로 웹 앱을 구현할 때 자주 사용하는 코딩 패턴입니다.
하위 요소에 각각 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트를 제어하는 방식입니다.
위와 같은 동작이 가능한 이유는 하위요소에서 이벤트가 발생시 버블링으로 상위요소에서도 해당 이벤트를 알 수 있기때문에 이벤트가 일어난 해당 요소만
event.target
을 사용하여 하위요소의 이벤트를 컨트롤 할 수 있습니다.
event.target
을 사용하여 이벤트가 발생한 요소가 어디인지 알아냅니다.innerHTML
이나 유사한 기능을 하는 스크립트로 요소 덩어리를 더하거나 뺄 수 있기 때문에 DOM 수정이 쉬워집니다.event.stopPropagation()
를 사용할 수 없습니다. <body>
<div style="margin: 50px" class="container">
<strong>To do list</strong>
<ul class="toDoList">
<li>
<input type="checkbox" id="input1" />
<label for="input1">이벤트 위임 공부하기</label>
</li>
<li>
<input type="checkbox" id="input2" />
<label for="input2">버블링 공부하기</label>
</li>
</ul>
</div>
<script>
let inputs = document.querySelectorAll("input");
inputs.forEach((input) => {
input.addEventListener("click", (e) => {
alert("click");
});
});
</script>
</body>
queryselectorAll()
를 사용하여 모든 input element를 가져온 다음 각 input element에 클릭 이벤트 리스너를 추가합니다. 체크박스를 클릭하면 위와 같이 이벤트가 발생합니다.
해당 코드만 사용한다면 문제가 없겠지만 추가적으로 리스트 아이템을 추가한다면 어떻게 되는지 보겠습니다.
<script>
let inputs = document.querySelectorAll("input");
inputs.forEach((input) => {
input.addEventListener("click", (e) => {
alert("click");
});
});
//추가 코드
var itemList = document.querySelector(".toDoList");
var li = document.createElement("li");
var input = document.createElement("input");
var label = document.createElement("label");
var labelText = document.createTextNode("추가된 input");
label.setAttribute("style", "color:red");
input.setAttribute("type", "checkbox");
input.setAttribute("id", "input3");
label.setAttribute("for", "input3");
label.appendChild(labelText);
li.appendChild(input);
li.appendChild(label);
itemList.appendChild(li);
</script>
이와 같이 적용되지 않는걸 확인 할 수 있습니다. 이벤트 등록 지점이 요소 생성 시점보다 먼저 일어났기떄문입니다, 수동적으로 요소 생성 코드를 이벤트 등록 지점 위에 작성도 가능하겠지만 코드가 지저분해질수 있으며 해당 코드에서 다시 추가로 생성된 요소에 이벤트를 등록하게되는 작업은 번거로운 작업입니다.
그렇기에 이벤트 위임을 사용하여 상위요소에서 하위요소 이벤트 처리를 해보겠습니다.
<script>
let container = document.querySelector(".container");
container.addEventListener("click", (e) => {
alert("click");
});
</script>
상위요소인 div
에 이벤트 위임하였습니다.
동일하게 작동하는것을 볼 수 있습니다.
한가지 유의할 점은 하위 모든 요소에 적용되어strong
등.. 불필요한 태그에도 적용된다는 점인데요.
event.target
를 사용하여 이벤트를 제어할 수 있습니다.
최종적으로 불필요한 태그에 적용시키지 않으면서 추가로 생성된 요소에도 적용되는지 확인해보겠습니다.
<script>
let container = document.querySelector(".container");
container.addEventListener("click", (event) => {
let target = event.target;
if (target.tagName === "INPUT") alert("click");
});
var itemList = document.querySelector(".toDoList");
var li = document.createElement("li");
var input = document.createElement("input");
var label = document.createElement("label");
var labelText = document.createTextNode("추가된 input");
label.setAttribute("style", "color:red");
input.setAttribute("type", "checkbox");
input.setAttribute("id", "input3");
label.setAttribute("for", "input3");
label.appendChild(labelText);
li.appendChild(input);
li.appendChild(label);
itemList.appendChild(li);
</script>
잘 작동하는걸 확인할 수 있습니다.
이벤트 위임 기능 참고 - CAPTAIN PANGYO
이벤트 위임 기능 참고 - JAVASCRIPT.INFO