JS의 이벤트 전파 메커니즘

1. 이벤트의 확산

자바 스크립트에서 이벤트가 발생하면 하위 요소와 상위 요소간에 전파됩니다. 이 스프레드는 세 단계로 나뉩니다.

  • 첫 번째 단계 : " 캡처 단계 " 라고하는 창 개체에서 대상 노드로의 전도 (상층에서 하단 계층으로) .
  • 두 번째 단계 : " 대상 단계 "(대상 단계) 라고하는 대상 노드에서 트리거됩니다 .
  • 세 번째 단계 : 윈도우 객체는 " 버블 링 단계 " 라고하는 대상 노드 (하단 계층에서 상위 계층으로)에서 다시 전송됩니다 .

이 3 단계 전파 모델을 사용하면 동일한 이벤트가 여러 노드에서 트리거 될 수 있습니다.


둘째, 코드 데모

<!--<div>节点之中有一个<p>节点。-->
<div>
  <p>点击</p>
</div>
/**
   * 如果对这两个节点,都设置click事件的监听函数
   * (每个节点的捕获阶段和冒泡阶段,各设置一个监听函数),
   * 共计设置四个监听函数。然后,对<p>点击,click事件会触发四次。
   * */
  var phases = {
    
    
    1: 'capture',
    2: 'target',
    3: 'bubble'
  };

  var div = document.querySelector('div');
  var p = document.querySelector('p');

  div.addEventListener('click', callback, true);
  p.addEventListener('click', callback, true);
  div.addEventListener('click', callback, false);
  p.addEventListener('click', callback, false);

  function callback(event) {
    
    
    var tag = event.currentTarget.tagName;
    var phase = phases[event.eventPhase];
    console.log("Tag: '" + tag + "'. EventPhase: '" + phase + "'");
  }
  
// 点击以后的结果
// Tag: 'DIV'. EventPhase: 'capture'
// Tag: 'P'. EventPhase: 'target'
// Tag: 'P'. EventPhase: 'target'
// Tag: 'DIV'. EventPhase: 'bubble'

1. 결과 분석

위 코드는 클릭 이벤트가 div 노드의 캡처 단계 및 버블 링 단계에서 한 번, p 노드의 대상 단계에서 두 번, 네 번 트리거되었음을 나타냅니다.

1. 捕获阶段:事件从div向p传播时,触发div的click事件;
2. 目标阶段:事件从div到达p时,触发p的click事件;
3. 冒泡阶段:事件从p传回div时,再次触发div的click事件。

그중 p 노드는 2 개의 모니터링 기능 (addEventListener 메소드의 세 번째 매개 변수가 다르기 때문에 2 개의 모니터링 기능이 바인딩 됨)이 있으므로 클릭 이벤트로 인해 모두 한 번 트리거됩니다. 따라서 p는 목표 단계에서 두 번 출력됩니다.

事件传播的最上层对象是window,接着依次是document,html(document.documentElement)和body(document.body)。
也就是说,上例的事件传播顺序,在捕获阶段依次为window、document、html、body、div、p
在冒泡阶段依次为p、div、body、html、document、window

2 、 addEventListener ()

addEventListener ()는 현재 노드 또는 객체의 특정 이벤트에 대한 리스너 함수를 정의하는 데 사용됩니다. 이 이벤트가 발생하면 모니터링 기능이 실행됩니다. 이 메서드에는 반환 값이 없습니다.

target.addEventListener(type, listener[, useCapture]);

이 메서드는 세 개의 매개 변수를받습니다.

  • 유형 : 이벤트 이름, 대소 문자를 구분합니다.
  • listener : 리스너 기능. 이벤트가 발생하면 리스너 함수가 호출됩니다.
  • useCapture : 모니터 기능이 캡처 단계 (캡처)에서 트리거되는지 여부를 나타내는 부울 값, 기본값은 false입니다 (모니터 기능은 버블 링 단계에서만 트리거 됨) . 이 매개 변수는 선택 사항입니다.

3 、 event.eventPhase

event.eventPhase 속성 은 이벤트의 현재 단계나타내는 정수 상수를 반환합니다 . 이 속성은 읽기 전용입니다.

event.eventPhase의 반환 값에는 네 가지 가능성이 있습니다.

  • 0 : 현재 이벤트가 발생하지 않았습니다.
  • 1 : 이벤트가 현재 캡처 단계에 있습니다. 즉, 상위 노드에서 대상 노드로 전파되는 중입니다.
  • 2 : 이벤트가 event.target 속성이 가리키는 노드 인 대상 노드에 도달합니다.
  • 3 : 이벤트가 버블 링 단계에 있습니다. 즉, 대상 노드에서 상위 노드로의 역 전파 과정에 있습니다.

4 、 event.currentTarget 与 event.target

이벤트가 발생하면 캡처 및 버블 링의 두 단계를 거쳐 여러 DOM 노드를 차례로 통과합니다. 따라서 어느 시점에서든 이벤트와 관련된 두 개의 노드가 있는데, 하나는 이벤트의 원래 트리거 노드 (event.target)이고 다른 하나는 이벤트가 현재 통과하고있는 노드 (event.currentTarget)입니다. 전자는 일반적으로 후자의 후손 노드입니다.

event.currentTarget 속성은 이벤트가 현재 위치한 노드, 즉 이벤트가 현재 통과하고있는 노드, 즉 현재 실행중인 모니터링 기능이 있는 노드를 반환합니다 . 이벤트가 전파되면이 속성의 값이 변경됩니다.

event.target 속성은 원래 이벤트를 트리거 한 노드, 즉 이벤트가 원래 발생한 노드를 반환합니다 . 이 속성은 이벤트가 전파 될 때 변경되지 않습니다.

이벤트 전파 과정에서 서로 다른 노드의 모니터링 기능에있는 event.target 및 event.currentTarget 속성의 값이 다릅니다.

// HTML 代码为
// <p id="para">Hello <em>World</em></p>
function hide(e) {
    
    
  // 不管点击 Hello 或 World,总是返回 true
  console.log(this === e.currentTarget);

  // 点击 Hello,返回 true
  // 点击 World,返回 false
  console.log(this === e.target);
}

document.getElementById('para').addEventListener('click', hide, false);

위 코드에서 em은 p의 자식 노드입니다. em 또는 p를 클릭하면 모니터링 기능이 실행됩니다. 이때 e.target은 항상 원래 클릭 위치의 노드를 가리키고 e.currentTarget은 이벤트 전파 프로세스 중에 전달되는 노드를 가리 킵니다.

모니터링 기능은 이벤트가 통과 할 때만 트리거되므로 e.currentTarget은 모니터링 기능 내에서 항상 이와 동일합니다. 이것은 이벤트 핸들러에 의해 등록 된 요소를 가리 킵니다!


세, 참고 자료

https://wangdoc.com/javascript/events/model.html
https://wangdoc.com/javascript/events/event.html#navbar
https://wangdoc.com/javascript/events/eventtarget.html#navbar

추천

출처blog.csdn.net/weixin_43974265/article/details/110531855