一、我们先分析其产生的原因:
1、当鼠标从父级移入子集时触发了父级的两个事件:a、父级的mouseout事件(父级离开到子集);b、由于事件冒泡影响,又触发了父级的mouseover事件(父级移入父级);
2、当鼠标从子集移出到父级时又触发了父级的两个事件:a、由于事件冒泡影响,父级触发了mouseout事件(父级移出父级);b、再触发了父级的mouseover事件(子集移入父级)
注:红色字体的解释是事件冒泡的奇妙之处。
二、解决方法:
首先必须先熟悉以下两个方法和一个事件属性:
a,b为节点
1、a.contains(b)
如果a包含b,返回true;否则返回false;a包含a同样返回true(不兼容火狐)
2、 a.compareDocumentPosition(b) 兼容火狐
这玩意就好玩了:
a在b之后返回2;
a在b之前返回4;
a被b包含返回8;
a包含b返回16;
a包含a返回0;
3、ev.relatedTarget
返回事件的目标节点相关的节点;
对于 mouseover 事件来说,该属性是鼠标指针移到目标节点上时所离开的那个节点。
对于 mouseout 事件来说,该属性是离开目标时,鼠标指针进入的节点。(IE9以下不兼容)
但IE7/8下有ev.toElement和ev.fromElement;
mouseover事件对应ev.fromElement
mouseout事件对应ev.toElement
接下来开始解决问题:
假设a是父级;b是与事件关联的节点:
解决原因1:
方法(1)a包含b返回true,a包含a返回true;
方法(2)a移出b(mouseout)返回4+16即返回20;a移入a(mouseover)返回0;
解决原因2:
方法(1)a包含a返回true,a包含b返回true
方法(2)a移出a返回0,b移入a返回4+16即返回20;
要让以上都不执行:
见代码:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>解决子集影响父级事件</title> <style type="text/css"> body { width: 100%; height: 100%; padding: 0; margin: 0;} #div1 { width: 200px; height: 200px; background: red; } #div2 { width: 100px; height: 100px; background: blue;position: absolute; top: 50px; left: 50px;} #txt { width: 800px; background: lime; color: red; height: 50px; line-height: 50px; font-size: 30px} </style> <script> window.onload=function(){ var oTxt = document.getElementById(‘txt‘); var a = document.getElementById(‘div1‘); var b = document.getElementById(‘div2‘); alert(b) a.onmouseover=function(ev){ var oEvent = ev || window.event; if(toAffect(a,oEvent,‘mouseover‘)){ oTxt.value += "移入"+" "; } } a.onmouseout=function(ev){ var oEvent = ev || window.event; if(toAffect(a,oEvent,‘mouseout‘)){ oTxt.value += "移出"+" "; } } } function toAffect(obj1,ev,event){ var obj2 = null; if(ev.relatedTarget){ obj2 = ev.relatedTarget; } else{ if(event == ‘mouseover‘){ obj2 = ev.fromElement; } else if(event == ‘mouseout‘){ obj2 = ev.toElement; } } if(obj1.contains){ return !obj1.contains(obj2); } else{ return !!(obj1.compareDocumentPosition(obj2)-20)&&a!=b; } } </script> </head> <body> <div id="div1"> 父级 <div id="div2">子集</div> </div> <input id="txt" type="text" /> </body> </html>
代码中的toAffect方法便是解决子集影响父级的方法。