
addEventListener() API를 이용해서 이벤트 등록을 할 수 있다.
const divs = document.querySelectorAll("div");
divs.forEach((div) => {
div.addEventListener("click", () => {
console.log("hi");
});
});
addEventListener()는 화면에 동적인 기능을 추가하기 위해서 사용되는 기능이다.
removeEventListener() API를 이용해서 이벤트 제거를 할 수 있다.
Event Bubbling)상위의 화면 요소란 한 단계 위에 있는 요소이고
HTML요소는 기본적으로 트리 구조를 가지고 있다.
<div class="three">
<div class="two">
<div class="one">눌러보세요!</div>
</div>
</div>
const logEvent = (event) => {
console.log(event.currentTarget.className);
};
const divs = document.querySelectorAll("div");
// Event Bubbling
divs.forEach((div) => {
div.addEventListener("click", logEvent);
});
querySelectorAll을 썼기 때문에 각 태그마다 이벤트가 등록되어 있다.
그래서눌러보세요!를 클릭하면one->two->three순으로console에 찍히는 것을 볼 수 있다.
만약 이벤트가 특정div태그에만 달려 있다면 위와 같은 동작 결과는 확인할 수 없다.
하위 요소에서 상위 요소로 이벤트가 전파되는 방식을 이벤트 버블링 (
Event Bubbling)이라고 한다.
Event Capture)body 태그부터 클릭 이벤트가 발생한 지점으로 찾아가는 그림이 나타난다.divs.forEach((div) => {
div.addEventListener("click", logEvent, {
capture: true,
});
});
addEventListener()API에서 옵션 객체에capture: true를 설정해주면 된다.
눌러보세요!를 클릭하면three->two->one순으로console에 찍히는 것을 볼 수 있다.
event.stopPropagation()const logEvent = (event) => {
event.stopPropagation();
console.log(event.currentTarget.className);
};
event.stopPropagation()을 입력하게 되면 이벤트 버블링에서는one만 찍히게 되고 이벤트 캡쳐에서는three만 찍히게 된다.
이벤트 버블링이나 이벤트 캡쳐처럼 이벤트 흐름을 제대로 알지 못하면, 예상하지 못한 에러가 발생할 수 있는데,event.stopPropagation()을 입력하게 되면 에러를 방지할 수 있다.
Event Delegation)TodoList에서 클릭 이벤트로 새로운 일정(태그)을 만들었다고 했을 때, 해당 일정(태그)에도 이벤트를 줘야 한다.(삭제, 수정 등의 이벤트가 태그에 자동으로 붙는 것이 아니다.)
추가된 일정(태그)에 이벤트를 주려면 이벤트 리스너를 새로 달아야 한다.
처음addEventListener()에 등록되지 않은 이벤트이기 때문이다.
이러한 작업은 매우 번거롭다.
번거로운 작업을 해결할 수 있는 방법이 이벤트 위임 (
Event Delegation)이다.
var itemList = document.querySelector(".itemList");
itemList.addEventListener("click", function (event) {
const input = event.target.closest("input");
if (!input) return;
alert("clicked");
});
클릭 했을 때
alert를 주는 이벤트이다.
input태그에 이벤트를 주고 싶을 때input태그들을 다 감싸고 있는 상위 태그의class이름(.itemList)으로 이벤트를 등록했다.
.itemList요소 안에 있는 모든 요소는click했을 때alert()가 실행된다.
<li>
<input type="checkbox" id="item2" />
<label for="item2">이벤트 캡쳐 학습</label>
</li>
const input = event.target.closest("input");
if (!input) return;
label요소도 이벤트를 같이 받기 때문에input요소만 이벤트로 받아서 처리할 수 있도록 해준다.
closest()는 메소드를 통해 자신부터 부모 요소 단위로 출발하여 각 요소가 지정한 선택자에 만족할 때까지 탐색한다.
이 중 가장 가깝게 조건에 만족한 부모 요소가 반환된다. 조건에 만족한 요소가 없으면null값을 반환한다.