이 글은 실제로 이벤트 요소의 하위 요소가 버블링되는 것을 방지하지 않습니다...
이벤트가 트리거되어야 하는지 여부를 결정하기 위해 하위 요소가 이벤트 요소에 버블링될 때 판단하는 것뿐입니다. 아...아니요, 이벤트 함수에서 관련 작업을 실행할지 여부가 되어야 합니다...
우선 여기를 클릭하세요: 문제 발생
참고: jquery의 mouseover/out 이벤트에도 이 문제가 있습니다.
해결책 1:
IE에는 mouseover 및 mouseout을 대체하는 mouseenter 및 mouseleave 이벤트가 있습니다.
인터넷에는 이 두 이벤트가 IE에서만 지원되고 다른 브라우저에서는 지원되지 않는다는 의견이 많습니다.
그러나 최신 버전의 Firefox와 Google은 mouseenter와 mouseleave를 지원합니다! ! ! ! !
또한 IE의 지원 범위는 [ie5이므로 IE를 뿌리면 안 됩니다...
다른 브라우저에서 테스트됨:
Firefox/3.6.28에서는 Mouseenter 및 mouseleave가 지원되지 않습니다. 어떤 버전의 Firefox가 이 두 이벤트를 지원할지는 알 수 없습니다...
Opera9.50 Alpha 및 Opera9.00 Beta에서는 지원되지 않습니다. 사실 이제 Opera를 테스트할 필요가 없습니다. 최신 버전의 Opera는 웹킷 커널을 기반으로 합니다...
Google 하위 버전에서는 테스트를 거치지 않았습니다...
물론 이러한 이전 버전의 브라우저는 기본적으로 무시될 수 있으므로 이것이 최선의 해결책이 되어야 합니다. mouseover 및 mouseout를 대체하려면 mouseenter 및 mouseleave 이벤트를 사용하십시오.
이 두 가지 이벤트의 예를 보려면 여기를 클릭하세요: mouseenter 및 mouseleave
참고: jquery에는 모든 브라우저와 호환되는 mouseenter 및 mouseleave 이벤트도 있습니다.
해결책 2:
위의 방법은 이전 버전의 Firefox 및 Google에서 지원되지 않습니다. 최대한의 호환성을 원한다면 아래를 계속 읽어보세요
이벤트 관련 요소를 얻기 위해 var reltg = e.관련Target ? e.관련Target : e.type == 'mouseout' ? e.toElement : e.fromElement를 사용합니다. 그런 다음 이 이벤트 관련 요소와 이벤트 요소 간의 관계(포함된 관계)를 이용하여 관련 이벤트 처리를 수행할지 여부를 결정합니다.
mouseout 이벤트의 경우 reltg는 마우스 포인터가 대상을 떠날 때 들어가는 노드입니다.
mouseover 이벤트의 경우 reltg는 마우스 포인터가 대상 노드로 이동할 때 떠나는 노드입니다.
li의 마우스아웃 이벤트 함수에서 reltg가 li의 하위 요소인 경우 관련 작업을 실행할 필요가 없습니다. reltg가 li의 상위 요소인 경우 관련 작업을 실행합니다.
다음 isMouseLeaveOrEnter 함수를 통해 li와 reltg 사이의 포함 관계를 판단할 수 있습니다.
//判断事件相关元素与li的关系 如果事件相关元素为li的子元素就返回false 反之返回true function isMouseLeaveOrEnter(e, handler) { if (e.type != 'mouseout' && e.type != 'mouseover') return false; var reltg = e.relatedTarget ? e.relatedTarget : e.type == 'mouseout' ? e.toElement : e.fromElement; while (reltg && reltg != handler) reltg = reltg.parentNode; return (reltg != handler); }; Li.onmouseout = function(e) { e = e||window.event; if (isMouseLeaveOrEnter(e,this)) { //运行相关操作 }; }
이 방법의 명백한 단점은 isMouseLeaveOrEnter에서 모든 상위 요소를 순회해야 한다는 것인데, 이는 성능 문제입니다.
해결책 3:
이 방법은 방법 2의 모든 상위 요소를 순회함으로써 발생하는 성능 문제를 최적화하는 li과 reltg 사이의 포함 관계를 결정하기 위해 비교DocumentPosition/contains를 사용한다는 점을 제외하면 방법 2와 아이디어가 동일합니다.
코드를 직접 살펴보겠습니다:
//判断node是否为parent的子元素 //if node == parent 也会返回true function contains(parent, node) { if(parent.compareDocumentPosition){ //ff var _flag = parent.compareDocumentPosition(node); return (_flag == 20 || _flag == 0)? true : false; }else if(parent.contains){ //ie return parent.contains(node); } }; Li.onmouseout = function(e) { e = e||window.event; var relatedEle = e.relatedTarget ? e.relatedTarget : e.type == 'mouseout' ? e.toElement : e.fromElement if (!contains(this, relatedEle)) { show.innerHTML=show.innerHTML+'0'; } }
compareDocumentPosition() 메서드는 두 노드를 비교하고 문서에서의 위치를 설명하는 정수를 반환합니다.
반환 값은 다음과 같습니다.
1: 상관없습니다. 두 노드는 동일한 문서에 속하지 않습니다.
2: 첫 번째 노드(P1)는 두 번째 노드(P2) 뒤에 위치합니다.
4: 첫 번째 노드(P1)는 두 번째 노드(P2) 앞에 위치합니다.
8: 첫 번째 노드(P1)는 두 번째 노드(P2) 내에 위치합니다.
16: 두 번째 노드(P2)는 첫 번째 노드(P1) 내에 위치합니다.
32: 관계가 없거나 두 노드가 동일한 요소의 두 속성입니다.
참고: 반환 값은 값의 조합일 수 있습니다. 예를 들어, 20을 반환한다는 것은 p2가 p1(16) 내부에 있고 p1이 p2(4) 앞에 있음을 의미합니다.
그리고 [ie8-은 CompareDocumentPosition() 메서드를 지원하지 않습니다. 대신 containDocumentPosition() 메서드는 nodeB가 다른 nodeA에 포함되어 있는지 확인하는 데 사용됩니다. )
위 내용은 이 글의 전체 내용입니다. 모두 마음에 드셨으면 좋겠습니다.