답변:
이벤트 버블 링 및 캡처는 다른 요소 내부의 요소에서 이벤트가 발생하고 두 요소가 해당 이벤트에 대한 핸들을 등록한 경우 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
첫 번째 ( div
will 에서 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 에는 useCapture
true 또는 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>