이벤트라고 하면 넷스케이프와 마이크로소프트 사이의 '브라우저 전쟁'으로 거슬러 올라간다. 당시에는 이벤트 모델에 대한 표준이 없었고 두 회사의 구현이 사실상 표준이었습니다. Netscape는 Navigator에서 "이벤트 캡처" 이벤트 시스템을 구현한 반면 Microsoft는 IE에서 "이벤트 버블링"이라는 기본적으로 반대되는 이벤트 시스템을 구현했습니다. 두 시스템의 차이점은 이벤트가 발생했을 때 해당 이벤트를 처리(응답)하는 관련 요소의 우선순위가 다르다는 점입니다.
다음 예에서는 두 이벤트 메커니즘의 차이점을 보여줍니다. 문서의 구조가 다음과 같다고 가정합니다.
이 세 가지 요소로 인해 요소가 중첩되어 있으므로 실제로 클릭하면 범위와 div가 클릭됩니다. 즉, 세 가지 요소 모두 클릭 이벤트를 처리할 수 있는 기회가 있어야 합니다. 이벤트 캡처 메커니즘에서 이 클릭 이벤트 처리 우선순위는 div > span >
나중에 W3C 사양에서는 브라우저가 캡처 및 버블링 메커니즘을 모두 지원하도록 요구했으며 개발자가 이벤트를 등록할 단계를 선택할 수 있도록 허용했습니다. 따라서 이벤트를 등록하는 표준 방법은 다음과 같습니다.
target.addEventListener(type, listening, useCapture Optional)
where:
◆ type: string, 모니터링할 이벤트 종류
◆ 리스너: 특정 이벤트가 발생할 때 알림을 받을 수 있는 리스너 객체(JavaScript 함수)
◆ useCapture: 불리언 값, 캡처 단계에 등록할지 여부
실제 애플리케이션 개발에서는 IE와의 호환성을 보장하기 위해(캡처를 지원하지 않기 때문에) 일반적으로 useCapture를 false로 지정합니다(기본값도 false입니다). 즉, 위의 간단한 예에서는 버블링 단계에만 이벤트를 등록합니다. 응답 순서는 a >
버블링의 부작용
위에서 언급했듯이 IE의 버블링 이벤트 모델은 기본적으로 사실상의 표준이 되었습니다. 하지만 버블링에는 부작용이 있습니다.
여전히 이전 문서 구조를 예로 들어 인터페이스의 메뉴 항목이라고 가정하면 사용자 마우스가 div를 떠날 때 메뉴가 숨겨지기를 원합니다. 그래서 우리는 div에 대한 mouseout 이벤트를 등록했습니다. 사용자가 div에서 마우스를 떼면 모든 것이 올바른 것입니다. 그리고 사용자 마우스가 a 또는 스팬에서 벗어나면 문제가 발생합니다. 이벤트 버블링으로 인해 이 두 요소에서 전달된 mouseout 이벤트가 div로 전파되어 마우스가 div를 벗어나지 않게 되고 메뉴가 미리 숨겨지게 됩니다.
물론 버블링의 부작용을 피하기는 어렵지 않습니다. 예를 들어 div 내부의 각 요소에 대해 mouseout 이벤트를 등록하고, 이벤트가 더 이상 확산되지 않도록 .stopPropagation() 메서드를 사용합니다. IE의 경우 이벤트 버블링을 취소하려면 이벤트 객체의 cancelBubble 속성을 false로 설정해야 합니다. 그러나 이는 여전히 브라우저 비호환 문제를 직접 처리하는 기존 방식으로 대체됩니다.
최적화 계획
Bubbling의 부작용을 피하기 위해 jQuery에서는 mouseenter 및 mouseleave 이벤트를 제공하므로 mouseover 및 mouseout 대신 사용하세요.
다음은 mouseenter와 mouseleave를 지원하는 jQuery 내부 함수 insideElement에서 발췌한 것입니다. 의견은 참고용으로만 번역되었습니다.
// 다음 함수를 사용하여 감지합니다. 이벤트가 다른 요소 내부에서 발생하는지 여부
//
var insideElement = function( event ) {
사용// jQuery.event.special.mouseenter에 mouse(over|out)가 아직 있는지 확인하고 mouseleave 핸들러 동일한 상위 요소 내에서
var parent = event.관련Target;
// 올바른 이벤트 유형 설정
event.type = event.data;// Firefox는 때때로 관련 타겟에 XUL을 할당합니다. 요소
// 이 요소의 경우 parentNode 속성에 액세스할 수 없습니다.
try {
// Chrome도 유사하지만 parentNode 속성에 액세스할 수는 있지만
// 결과는 null입니다.
if ( parent && parent !== document && !parent.parentNode ) {
return
}
// DOM 트리 위로
while ( parent && parent !== this ) {
parent = parent.parentNode;
}
if ( parent !== this ) {
// 실제로 하위 요소가 아닌 요소에 있으면 괜찮습니다. 이벤트를 처리하세요.
jQuery .event.handle .apply( this, 인수 );
}
// 마우스가 XUL 요소에 배치되었을 가능성이 높기 때문에 해당 요소가 남아 있다고 가정합니다.
} catch(e) { }
},
결론
jQuery에서는 mouseenter 및 mouseleave 이벤트를 사용하여 이벤트 버블링의 부작용을 피할 수 있습니다.
원문: http://www.ituring.com.cn/article/420