TIL : Event(버블링, 캡쳐,위임)란!?

군밤먹으면서코딩·2021년 6월 1일
0

javascript

목록 보기
15/16
post-thumbnail

브라우저는 어떻게 화면 내의 특정 이벤트를 감지할까?? 또 감지한 이벤트를 어떻게 다른 화면에 전파할까??

이벤트 등록

웹 어플리케이션에서 사용자의 입력을 받기 위한 기능

<button>button<button>
const btn = document.querySelector("button");

btn.addEventListener("click", () => console.log("hello"));
  • 우리는 addEventListener()를 사용하여 사용자의 입력에 따른 추가적인 동작들을 구현할 수 있다.
  • click 이벤트 뿐만 아니라, keydown(키를 누를때) 등 다양한 기능들을 손쉽게 추가 가능하다!

이 때, 브라우저는 이러한 이벤트들을 감지하는 2가지 방법!

이벤트 전달 방식(2가지)

이벤트 버블링

이벤트 버블링이란, 특정 화면 요소에서 발생한 이벤트가 상위 요소까지 전달되는 현상을 말한다.

예를 들자면 body>div>div>div 와 같은 구조를 가진 코드가 있다면,
마지막 div에서 발생한 이벤트가 버블링을 통하여 body까지 전달되는 현상을 이벤트 버블링이라 할 수 있다!

  • 위와 같은 구조를 트리 구조 라고 하는데, 여기서 말하는 상위 요소란, 특정 요소 바로 위의 요소를 일컫는다!
 <div class="one">
      <div class="two">
            <div class="three"></div>
      </div>
 </div>
//js코드
let divs = document.querySelectorAll("div");
divs.forEach(function (div) {
    div.addEventListener("click", logEvent);
});

function logEvent(event) {
    console.log(event.currentTarget.className);
}

이렇게 가장 하위 요소의 이벤트가 상위 요소로 계속해서 전달되는 것을 이벤트 버블링 이라 한다!
단, 지금은 모든 태그에 이벤트가 걸려있으나 특정 태그에만 이벤트를 건다면 이와같은 결과는 나타나지 않는다!

이벤트 캡쳐

이벤트 캡쳐는 버블링과 반대되는 현상이다. 상위요소 -> 하위요소로 이벤트 전파

var divs = document.querySelectorAll('div');
divs.forEach(function(div) {
	div.addEventListener('click', logEvent, {
		capture: true // default 값은 false입니다.
	});
});

function logEvent(event) {
	console.log(event.currentTarget.className);
}

버블링과의 차이점은 이벤트가 발생한 해당 요소를 가장 상위요소에서 부터 찾아내려간다는 점이다! 위의 버블링은 가장 하위 요소의 class name인 three->two->one 순으로 출력이 됐으나, 캡쳐링은 one->two->three로 출력된다.

참고 사이트 에서는 버블링캡쳐링을 방지하기 위해 stopPropagation을 사용할 수 있다고 나와있다. 이 API는 이벤트의 전파를 막는 용으로 사용되는데, 예기치 못한 버그를 발생시킬 수도 있는 위험성을 가지고 있다. 때문에 무분별한 사용은 조심해야한다!🙂

  • 버블링의 경우 : 클릭한 요소의 이벤트만 실행 (상위 요소 전파를 막는다)
  • 캡쳐의 경우 : 클릭한 요소의 최상위 이벤트만 실행(하위 요소 전파를 막는다)

이벤트 위임(Event Delegation)

하위 요소에 이벤트를 일일히 붙이지 않고, 상위 요소에서 이를 제어한다!! 라고 이해

예제를 살펴보쟈!!!!

 <div class="container">
       <div class="one">
            <div class="two">
                 <div class="three"></div>
            </div>
       </div>
 </div>
//js코드
const divs = document.querySelectorAll("div");

divs.forEach(function (div) {
    div.addEventListener("click", (e) => alert(e.currentTarget.className));
});

const container = document.querySelector(".container");

let div = document.createElement("div");
div.setAttribute("class", "four");

container.appendChild(div);

상단의 html 코드를 살펴볼 때, 만약 네번째 class를 js코드에서 추가적으로 삽입한다면 어떻게 될까?

currentTarget.className이 마지막 추가한 div에는 적용되지 않는다!

  • 이유는 divs를 선언하고 이벤트를 줄 당시에는 three까지만 적용이 된 상태이기 때문이다.
  • 즉 four는 위의 코드가 실행될 당시에는 적용되지 않는 것!
  • 그렇다면 이렇게 새로운 요소가 추가될 때마다 따로 이벤트를 선언해야하는가!?🧐

이럴 때 사용하는 것이 이벤트 위임!!

위의 코드를 수정해보자!

// const divs = document.querySelectorAll("div");

// divs.forEach(function (div) {
//     div.addEventListener("click", (e) => alert(e.currentTarget.className));
// });

const container = document.querySelector(".container");

container.addEventListener("click", (e) => alert(e.currentTarget.className));
let div = document.createElement("div");
div.setAttribute("class", "four");

container.appendChild(div);
  • container라는 상위 요소에서 하위 요소들의 이벤트를 통제하는것!

  • 결과는 container 하위의 요소들에 모두 container 라는 alert메세지가 출력되는 것을 볼 수 있다!

  • 버블링 효과를 통해 이같은 결과를 도출해낼 수 있는것.

  • 이 방식을 사용하면 요소가 추가되더라도 하나 하나 이벤트를 붙여줄 필요가 없다!

공부한 자료 : https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/

0개의 댓글