이안의 평일코딩

이벤트 관리 방법 (버블링, 캡쳐링, 이벤트 위임) 본문

Front-end/JavaScript

이벤트 관리 방법 (버블링, 캡쳐링, 이벤트 위임)

이안92 2021. 2. 26. 12:44
반응형

 

 

 

 이벤트란?

클릭이나 스크롤을 내리는 등 사용자와 웹페이지가 상호 작용을 하며 브라우저가 감지하는 것을 말한다. 이벤트 리스너, 이벤트 핸들러는 어떤 이벤트 발생 시 처리하는 함수이다. 자주 사용되는 DOM이벤트로 click(마우스 왼쪽 클릭), contextmenu(마우스 오른쪽 클릭), keydown(키보드 누를 때), keyup(키보드 뗄 때), submit, focus 등이 있다.

 

 이벤트 등록 방법

 

인라인 방식 (inline)

이벤트를 HTML 요소의 속성으로 직접 지정하는 방식이다. 단점은 HTML 코드에 자바스크립트를 추가해서 코드가 섞여 유지 보수에 좋지 못하다는 점이다.

<button onclick="alert('Hello World!);">Click</button>
프로퍼티 방식 (Property)

인라인 방식의 단점을 보완하여 자바스크립트 코드에 프로퍼티 등록 방식이다. 하나의 이벤트 핸들러 프로퍼티엔 하나의 이벤트 핸들러 바인딩이 가능하다는 단점이 있다. 아래의 코드를 실행하면 2번째 코드인 ‘Hello World!!!’만 출력된다.

<button onclick="testBtn">click</button>

<script>
  let testBtn = document.querySelector('#testBtn');
  testBtn.onclick=function(){
    alert('Hello World!');
  };
  testBtn.onclick=function(){
    alert('Hello World!!!');
  };
</script>
addEventListener() 방식

프로퍼티방식은 1개의 이벤트 핸들러만 바인딩 가능하지만 addEventListener() 방식은 하나 이상 가능하다. IE9 이상에서 동작하며 IE8 이하에서는 attachEvent()를 사용한다. 버블링과 캡쳐링을 지원한다.

<button id="testBtn2">click</button>
// 프로퍼티 방식과 달리 onclick이 없다

<script>
  let testBtn2 = document.querySelector('#testBtn2')
  function testFunc(){
    alert('Hello World!');
  }
  testBtn2.addEventListener('click', testFunc);
  testBtn2.addEventListener('click', Function(){
    alert('Hello World!!!');
  }
  // "on"이 붙은 이벤트를 사용하지 않는다. onclick아닌 click
</script>
이벤트리스너 삭제 방법

onclick은 null값을 주고 addEventListenr()는 removeEventListener()로 삭제한다.

elem.onclick = null;
testBtn2.removeEventListener('click', testFunc);

 

 이벤트 버블링 & 캡쳐링

 

이벤트 버블링(bubbling)

이벤트 발생 시 요소에 할당된 핸들러 동작 후에 최상단의 조상요소 만날 때까지 부모요소 핸들러를 동작하는 것이다.

<form onclick="alert('form')">FORM
  <div onclick="alert('div')">DIV
    <p onclick="alert('p')">P</p>
  </div>
</form>

P를 누르면 p, div, form 순으로 alert가 뜬다. Most deeply nested element(가장 깊게 중첩된 요소)인 p의 onclick 핸들러 동작 -> 바깥의 div의 핸들러 동작 -> 바깥의 form이 동작하면서 document 객체를 만날 때까지 동작하게 된다.

 

버블링을 중단하기 위해서는 event.stopPropagation()을 이용하면 된다. 아래의 click 버튼을 눌려도 alert 창이 뜨지 않는다.

<body onclick="alert('여기까지 버블링 도달 못함')">
  <button onclick="event.stopPropagation()">click</button>
</body>

event.stopPropagation()은 위쪽으로 일어나는 버블링은 막지만 다른 핸들러 동작은 막지 못하는데,

다른 핸들러 동작도 막기 위해서는 event.stopImmediatePropagation()을 사용한다.

 

이벤트 캡쳐링(capturing)

버블링의 반대로 이벤트가 하위 요소로 전파되는 것이다. 버블링은 전달에 사용하였다면 캡쳐링은 탐색할 때 이용한다.

elem.addEventListener(..., {capture:true})
elem.addEventListener(..., true)

// 제거
elem.removeEventListener(..., true)

false가 default 값으로 핸들러는 버블링 단계에서 동작하는 것이고 {capture:true}또는 그냥 true값을 주면 캡쳐링 단계에서 동작한다.

 

 이벤트 위임

하나의 부모에 이벤트를 등록하여 부모가 이벤트를 위임하는 방식이다. 하위 요소에 각각 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트들을 제어한다. 동적인 요소들을 처리하기 수월하고 이벤트 핸들러를 더 적게 등록해주기 때문에 메모리를 절약할 수 있다는 장점이 있다. 하위 요소가 많아질수록 이벤트리스너를 다는 작업이 번거롭기 때문에 이벤트 위임을 사용하는 것이다.

 

참고 사이트

velog.io/@ljinsk3/JavaScript%EB%A1%9C-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0

goddaehee.tistory.com/269

www.zerocho.com/category/JavaScript/post/57432d2aa48729787807c3fc

ko.javascript.info/bubbling-and-capturing

ko.javascript.info/introduction-browser-events

ko.javascript.info/event-delegation

joshua1988.github.io/web-development/javascript/event-propagation-delegation/

반응형
Comments