2011-11-18 5 views
7

알다시피, 이벤트는 일반적으로 자바 스크립트에서 버블 링되므로 이벤트를 발생시키는 요소의 이벤트 핸들러가 먼저 실행 된 다음 부모 요소의 이벤트 핸들러가 호출되는 식으로 계속됩니다. 이 문제는 현재 작업하고있는 프로젝트에서 몇 가지 문제가 발생합니다. 실행 순서가 반대로 변경됩니다.자바 스크립트에서 역 이벤트 버블 링

$(element).mouseover(function(){ 
    var that = this; 
    setTimeout(function() { 
     //actual event handler, but references to "this" are replaced with "that" 
    },$(this).parents().length) 
}); 

그래서 기본적으로 이벤트 핸들러가 짧은 시간 종료 후 실행, 대기 시간이 DOM 트리에서 요소의 깊이에 따라 달라집니다

나는 시간 제한을 사용하는 솔루션을 figuered : html 요소의 이벤트 처리기가 즉시 실행되고 body 요소의 이벤트 처리기가 1ms를 기다린 후 실행됩니다. 따라서 이벤트의 실행 순서가 바뀝니다.

첫 번째 테스트의 결과는 긍정적이지만,이 솔루션에 문제가 있는지 또는 단점이 있는지 확실하지 않습니다. 이 솔루션에 대해 어떻게 생각하십니까? 이 문제를 해결하는 방법에 대한 다른 아이디어 또한 높이 평가됩니다.

+1

부모님의 * 금액 *을 제한 시간 (밀리 초)으로 설정하는 이유를 알지 못합니다. – pimvdb

+2

그는 리프 요소에서 이벤트 처리기를 실행하는 것이 너무 지연되어 체인에서 마지막으로 실행되도록하기 위해이 작업을 수행하고 있습니다. – WTK

답변

14

역 이벤트 버블 링을 캡처 단계라고합니다.

는 캡처 단계는 기존의 플랫폼에서 작동하지 않습니다 물론

el.addEventListener("click", function() { 
    console.log("i run in capture"); 
}, true); 

에서 트리거하도록 Event.addEventListener에 세번째 인수로 DOM event architecture

패스 true를 참조하십시오. 이벤트 시스템을 에뮬레이트하려면 DOM3 이벤트가 필요합니다. 기여할 수 있습니다. DOM-shim

+0

그래, 물론, 모든 브라우저에서 구현되지 않았다는 것만 제외하면. http://www.quirksmode.org/js/events_order를 참조하십시오.html – WTK

+1

@WTK 기존 플랫폼에 대해 누가 신경 쓰겠습니까? – Raynos

+3

@Raynos 고객 ^^ –

0

처리 된 모든 이벤트에 대해 부모의 수를 설정하기 위해 this으로 시작하는 DOM을 위쪽으로 탐색해야한다는 사실이 솔루션의 큰 단점임을 알 수 있습니다.

모든 이벤트 핸들러에서 이와 같은 방식으로 트래 버핑 = 성능 저하.

+0

이벤트가 시작될 때마다 문서 루트에서 이벤트를 트리거 한 요소까지 루트에서 맨 아래까지 계속 실행됩니다. 핸들러 코드에서 문서 루트까지 추가 이동을하는 것은 과도한 시간을 소비하지 않습니다. –

0

에뮬레이트하려고 할 수도 있지만 문제가 될 수 있습니다.

매우 간단한 예입니다 (jsfiddle에 있음). 아이디어는 각 이벤트의 콜백을 집계하고 document 이벤트 핸들러에서 역순으로 호출하는 것입니다 (다음 클릭시 새 대기열을 보장하기 위해 목록도 지 웁니다).

<div id="a"> 
    <div id="b"> 
     <a href="/test">Click Me!</a> 
    </div> 
</div> 
var cb = []; 

$(document).click(function(evt){ 

    cb.unshift(function(){ 
     console.log('document'); 
    }); 
    var i; 
    for(i=0; i<cb.length; ++i){ 
     cb[i].call(null, evt); 
    } 
    cb = []; 
}); 

$("#a").click(function(){ 
    cb.unshift(function(){ 
     console.log('div#a'); 
    }); 
}); 

$("#b").click(function(){ 
    cb.unshift(function(){ 
     console.log('div#b'); 
    }); 
}); 

$('a').click(function(evt){ 
    cb.unshift(function(evt){ 
     evt.preventDefault(); 
     console.log('a'); 
    }); 
}); 

아마 당신은 당신의 디자인을 변경해야합니까? 더 많은 정보를 게시 할 수 있습니까? 왜 이벤트 캡처가 필요합니까?

+0

답변 해 주셔서 감사합니다. 이 역 이벤트 처리기 실행이 필요한 이유는 매우 복잡하고 간단히 설명하기 어렵습니다. 기본적으로, 임의의 html 문서의 다른 요소에 대한 mouseover 핸들러가 있습니다. 내부 요소를 가져 오기 전에 외부 요소 위로 마우스 포인터를 이동하기 때문에 일반적으로 외부 요소의 이벤트 처리기가 먼저 실행됩니다. 그러나 내부 요소가 들어있는 요소에는 모든 채우기가 없으므로이 작업은 실패합니다. 내부 요소에 이르기 위해 외부 요소 위로 이동하십시오. 그래서 일관된 동작을 위해 순서를 뒤집을 수 있습니다. – Simon

+0

흠 ... 당신은 항상 다음과 같은 일종의 '상속'을 사용할 수 있습니다. http://jsfiddle.net/GEFAq/ 2/그리고 그것은 작동해야합니다 (트리거는 동기식입니다, 내가보기에는). 이것은 기본 개념입니다 - 요소 처리기에서 전파를 중지하고 다른 작업을 수행하기 전에 부모 요소에서 동일한 이벤트를 트리거합니다. –

+0

그러나, 만약 당신이 정말로 오래된 브라우저에 신경 쓰지 않는다면, @ Raynos 솔루션을 가지고 귀찮게하지 마세요. –

관련 문제