답변:
이벤트 버블 링 및 캡처는 다른 요소 내부의 요소에서 이벤트가 발생하고 두 요소가 해당 이벤트에 대한 핸들을 등록한 경우 HTML DOM API에서 이벤트 전파의 두 가지 방법입니다. 이벤트 전파 모드 는 요소가 이벤트를 수신하는 순서를 결정 합니다 .
버블 링을 통해 이벤트는 먼저 가장 안쪽 요소에 의해 캡처되고 처리 된 다음 외부 요소로 전파됩니다.
캡처하면 이벤트가 가장 바깥 쪽 요소에 의해 먼저 캡처되어 안쪽 요소로 전파됩니다.
캡처는 "트릭 링"이라고도하며 전파 순서를 기억하는 데 도움이됩니다.
물방울, 거품
예전에는 Netscape가 이벤트 캡처를 옹호했고 Microsoft는 이벤트 버블 링을 홍보했습니다. 둘 다 W3C Document Object Model Events 표준 (2000)의 일부입니다.
IE <9는 이벤트 버블 링 만 사용 하지만 IE9 + 및 모든 주요 브라우저는 둘 다를 지원합니다. 반면 에 복잡한 DOM 의 경우 이벤트 버블 링 성능이 약간 떨어질 수 있습니다 .
addEventListener(type, listener, useCapture)버블 링 (기본값) 또는 캡처 모드에서 이벤트 핸들러를 등록 하는 데 사용할 수 있습니다 . 캡처 모델을 사용하려면으로 세 번째 인수를 전달하십시오 true.
<div>
<ul>
<li></li>
</ul>
</div>
위의 구조에서 li요소 에서 클릭 이벤트가 발생했다고 가정하십시오 .
캡처 모델에서 이벤트는 div첫 번째 ( divwill 에서 click 이벤트 핸들러가 먼저 실행 됨)에 의해 처리 된 다음 ul대상 요소에서 마지막으로 처리됩니다 li.
버블 링 모델에서는 반대 현상이 발생합니다. 이벤트는 먼저 li, 그 다음으로 ul, 마지막으로 div요소가 처리합니다.
자세한 내용은
아래 예에서 강조 표시된 요소를 클릭하면 이벤트 전파 흐름의 캡처 단계가 먼저 발생하고 버블 링 단계가 발생 함을 알 수 있습니다.
var logElement = document.getElementById('log');
function log(msg) {
logElement.innerHTML += ('<p>' + msg + '</p>');
}
function capture() {
log('capture: ' + this.firstChild.nodeValue.trim());
}
function bubble() {
log('bubble: ' + this.firstChild.nodeValue.trim());
}
function clearOutput() {
logElement.innerHTML = "";
}
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
divs[i].addEventListener('click', capture, true);
divs[i].addEventListener('click', bubble, false);
}
var clearButton = document.getElementById('clear');
clearButton.addEventListener('click', clearOutput);
p {
line-height: 0;
}
div {
display:inline-block;
padding: 5px;
background: #fff;
border: 1px solid #aaa;
cursor: pointer;
}
div:hover {
border: 1px solid #faa;
background: #fdd;
}
<div>1
<div>2
<div>3
<div>4
<div>5</div>
</div>
</div>
</div>
</div>
<button id="clear">clear output</button>
<section id="log"></section>
useCapture현재 IE> = 9에서 지원됩니다. source
triclkling은 동일 capturing? 대한 크록 포드 회담 Trickling v. Bubbling이 비디오 이야기에서 - youtube.com/watch?v=Fv9qT9joc0M&list=PL7664379246A246CB의 주변 1 hr 5 minutes.
trickle down=> onElement=>bubble up
기술:
quirksmode.org 에 이에 대한 멋진 설명이 있습니다. 간단히 말해서 (quirksmode에서 복사) :
이벤트 캡처
이벤트 캡처를 사용하는 경우
| | ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 \ / | | | ------------------------- | | Event CAPTURING | -----------------------------------element1의 이벤트 핸들러가 먼저 실행되고 element2의 이벤트 핸들러가 마지막으로 실행됩니다.
이벤트 버블 링
이벤트 버블 링을 사용하는 경우
/ \ ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 | | | | | ------------------------- | | Event BUBBLING | -----------------------------------element2의 이벤트 핸들러가 먼저 실행되고 element1의 이벤트 핸들러가 마지막으로 실행됩니다.
무엇을 사용해야합니까?
그것은 당신이하고 싶은 것에 달려 있습니다. 더 나은 없습니다. 차이점은 이벤트 핸들러 실행 순서입니다. 대부분의 경우 버블 링 단계 에서 이벤트 핸들러를 시작하는 것이 좋지만 더 일찍 실행해야 할 수도 있습니다.
요소 1과 요소 2가 2 개있는 경우 요소 2는 요소 1 안에 있고 두 요소가 모두 포함 된 이벤트 핸들러를 연결하면 onClick이라고 말할 수 있습니다. 이제 요소 2를 클릭하면 두 요소 모두에 대한 eventHandler가 실행됩니다. 이제 질문은 이벤트가 실행될 순서입니다. 요소 1에 첨부 된 이벤트가 먼저 실행되면 이벤트 캡처라고하고 요소 2에 첨부 된 이벤트가 먼저 실행되면이를 이벤트 버블 링이라고합니다. W3C에 따라 이벤트는 대상에 도달 할 때까지 캡처 단계에서 시작하여 요소로 돌아와 버블 링을 시작합니다.
캡처 및 버블 링 상태는 addEventListener 메소드의 useCapture 매개 변수로 알려져 있습니다.
eventTarget.addEventListener (type, listener, [, useCapture]);
기본적으로 useCapture는 false입니다. 그것은 버블 링 단계에 있다는 것을 의미합니다.
var div1 = document.querySelector("#div1");
var div2 = document.querySelector("#div2");
div1.addEventListener("click", function (event) {
alert("you clicked on div 1");
}, true);
div2.addEventListener("click", function (event) {
alert("you clicked on div 2");
}, false);
#div1{
background-color:red;
padding: 24px;
}
#div2{
background-color:green;
}
<div id="div1">
div 1
<div id="div2">
div 2
</div>
</div>
참과 거짓을 바꾸어보십시오.
the event will start in the capturing phase untill it reaches the target comes back to the element and then it starts bubbling. addEventListener 에는 useCapturetrue 또는 false로 설정할 수있는 매개 변수 만 있습니다. 및 HTML 4.0, 이벤트 리스너는 요소의 속성으로 지정된 및 useCapture defaults to false. 작성한 내용을 확인하는 사양에 연결할 수 있습니까?
이 주제를 설명하는 데 javascript.info 에서이 학습서 가 매우 명확 하다는 것을 알았습니다 . 그리고 마지막 3 점 요약은 실제로 중요한 점에 대해 이야기하고 있습니다. 나는 여기에 인용한다.
- 이벤트는 먼저 가장 깊은 대상으로 캡처 된 다음 버블 업됩니다. IE <9에서는 거품 만 발생합니다.
- 모든 처리기
addEventListener는 마지막 인수를 제외 하고 버블 링 단계에서 작동하며true, 캡처 단계에서 이벤트를 포착하는 유일한 방법입니다.- 버블 링 / 캡쳐는
event.cancelBubble=true(IE) 또는event.stopPropagation()다른 브라우저에 의해 중지 될 수 있습니다 .
Event.eventPhase이벤트가 대상에 있는지 또는 다른 곳에서 왔는지 알려줄 수 있는 속성 도 있습니다.
브라우저 호환성은 아직 결정되지 않았습니다. Chrome (66.0.3359.181) 및 Firefox (59.0.3)에서 테스트했으며 지원됩니다.
허용 된 답변에서 이미 훌륭한 스 니펫을 확장 하면 eventPhase속성을 사용하여 출력됩니다.
var logElement = document.getElementById('log');
function log(msg) {
if (logElement.innerHTML == "<p>No logs</p>")
logElement.innerHTML = "";
logElement.innerHTML += ('<p>' + msg + '</p>');
}
function humanizeEvent(eventPhase){
switch(eventPhase){
case 1: //Event.CAPTURING_PHASE
return "Event is being propagated through the target's ancestor objects";
case 2: //Event.AT_TARGET
return "The event has arrived at the event's target";
case 3: //Event.BUBBLING_PHASE
return "The event is propagating back up through the target's ancestors in reverse order";
}
}
function capture(e) {
log('capture: ' + this.firstChild.nodeValue.trim() + "; " +
humanizeEvent(e.eventPhase));
}
function bubble(e) {
log('bubble: ' + this.firstChild.nodeValue.trim() + "; " +
humanizeEvent(e.eventPhase));
}
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
divs[i].addEventListener('click', capture, true);
divs[i].addEventListener('click', bubble, false);
}
p {
line-height: 0;
}
div {
display:inline-block;
padding: 5px;
background: #fff;
border: 1px solid #aaa;
cursor: pointer;
}
div:hover {
border: 1px solid #faa;
background: #fdd;
}
<div>1
<div>2
<div>3
<div>4
<div>5</div>
</div>
</div>
</div>
</div>
<button onclick="document.getElementById('log').innerHTML = '<p>No logs</p>';">Clear logs</button>
<section id="log"></section>