«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

방춘덕(고양이 키우면 지을 이름)의 개발 블로그입니다.

event bubbling, capturing, delegation 본문

JS

event bubbling, capturing, delegation

방춘덕 2019. 12. 27. 06:37

  1. 시작하며
  2. event bubbling
  3. event capturing
  4. event delegation

1. 시작하며


이 글에서 알아볼 것은 JS에서 element에 이벤트를 추가했을 때 관한 동작 방식인데, 이 내용을 이해하지 못하고 코드를 작성한다면 예상치 못한 일들이 벌어질 수 있기 때문이다.

<div onclick="alert('div')">
  <span>이 텍스트는 span안에 있음.</span>
</div>

이 코드를 실행해보면 조금 이상하다는 것을 알 수 있다. div을 클릭하지 않았지만, div의 onclick event가 호출되는 것을 볼 수 있다. 위에서도 언급했듯, 이에 관한 내용을 숙지해야 하만 프로그래머의 의도대로 코드를 작성할 수 있을 것이다.

2. event bubbling


<section onclick="alert('section')">
  section
  <article onclick="alert('article')">
    article
    <div onclick="alert('div')">
      div
    </div>
  </article>
</section>

위 코드는 다음과 같은 순서로 실행된다. div -> article -> section 이것이 바로 event bubbling이다.

event가 발생하면 거품이 일어나듯 부모를 통해 자신의 event를 먼저 실행하고, 그다음 부모의 event를 반복해서 실행한다.

 

그렇다면 여기서 div를 클릭했을 때 event bubbling을 중지시키고 싶을 수 있다.

<section onclick="alert('section')">
  section
  <article onclick="alert('article')">
    article
    <div onclick="alert('div'); event.stopPropagation()">
      div
    </div>
  </article>
</section>

위와 같이 event의 stopPropagation 함수를 호출하면 event bubbling이 중단되며 부모 element들의 event들이 호출되지 않는다. 만약 자기 자신을 포함한 모든 호출을 막고 싶다면 stopImmediatePropagation를 사용하면 된다.

하지만, 이 또한 협업 등을 진행할 때 다른 프로그래머가 의도한 대로 event가 호출되지 못해 문제가 생길 수도 있으므로 매우 조심해서 사용할 것을 권장한다. (기본적으로는 event bubbling을 방해하지 않는 것이 좋다고 한다.)

 

대부분의 이벤트들은 모두 event bubbling이 가능하며 몇몇 소수의 event들(Ex. focus)은 불가능하다.

3. event capturing


<section class="click-event">
  section
  <article class="click-event">
    article
    <div class="click-event">
      div
    </div>
  </article>
</section>
const elements = document.getElementsByClassName('click-event')
console.log(elements)
for (const element of elements) {
  element.addEventListener("click", e => alert(`capturing: ${e.currentTarget.tagName}`), true) // { capture: true }
  element.addEventListener("click", e => alert(`bubbling: ${e.currentTarget.tagName}`))
}

위 코드를 실행시켜본다면 아래와 같이 순서로 실행된다.

  1. capturing 단계
    • capturing: section -> capturing: article -> capturing: div
  2. 목표 단계
    • capturing과 bubbling이 같이 일어나는 곳, 위 코드에서는 div가 목표 단계에 해당
  3. bubbling 단계
    • bubbling: div -> bubbling: article -> bubbling: section

위처럼 최상위 부모부터 자식까지 event가 실행되는 것이 event capturing이며  이 순서는 event 객체의 eventPhase라는 변수를 통해 현재 어떤 단계인지 알아올 수 있다. (1: capturing, 2: target, 3: bubbling)

 

추가적으로 capture를 true로 등록했다면 listener에서 제거할 때 또한 capture를 true로 하여 제거해야 한다.

4. event delegation


 

<section onclick="alert('section')">
  section
  <article onclick="alert('article')">
    article
    <div onclick="alert('div')">
      div
    </div>
  </article>
</section>

다시 이 코드를 봐보자. 객체를 클릭했을 때 클릭한 대상의 태그를 alert으로 띄우는 코드인데, 이를 더 효율적으로 작성할 수 있는 방법이 event delegation이다.

 

event delegation은 비슷한 방식으로 처리되는 파편화된 event들을 하나로 묶어서 처리하는 방법으로 이는 브라우저의 메모리를 절약할 수 있고, (event listener를 생성할 때마다 브라우저의 메모리가 사용됨) event 대상을 동적으로 추가 삭제가 가능하다.

 

위 코드를 event delegation 패턴으로 묶어보면 아래와 같다.

<section id="section">
  section
  <article>
    article
    <div>
      div
    </div>
  </article>
</section>
const section = document.getElementById('section')
section.addEventListener('click', e => alert(e.target.tagName))

이 글을 작성할 때 읽은 감사한 자료들.


https://javascript.info/bubbling-and-capturing

 

Bubbling and capturing

 

javascript.info

https://gomakethings.com/whats-the-difference-between-javascript-event-delegation-bubbling-and-capturing/

 

What's the difference between JavaScript event delegation, bubbling, and capturing?

Yesterday, I wrote about why event delegation is better than attaching events to specific elements. In response, my buddy Andrew Borstein asked: What’s the difference between event delegation/bubbling/capturing? This is a great question that I get fairly o

gomakethings.com

https://www.quirksmode.org/js/events_order.html

 

Javascript - Event order

See section 7D of the book. Netscape 4 only supports event capturing, Explorer only supports event bubbling. Netscape 6 and Konqueror support both, while Opera and iCab support neither. On the Introduction to events page I asked a question that at first si

www.quirksmode.org

https://javascript.info/event-delegation

 

Event delegation

 

javascript.info

 

'JS' 카테고리의 다른 글

ECMAScript와 그 역사  (0) 2020.01.10
polyfill과 transpiler  (0) 2020.01.04
closure  (0) 2019.12.20
prototype과 prototype chain  (0) 2019.12.16
scope  (1) 2019.12.13