相对定位父子元素触发mouseover和mouseout事件实验

来源:互联网 发布:恶意软件清理工具 编辑:程序博客网 时间:2024/05/16 09:00

最近做的一个项目中有个功能是鼠标移动到某一块id为A,然后A的子元素id为B在下方紧贴着父元素A显示出来,B里面的内容是鼠标移动到A元素上才请求服务端获取数据。

我使用了mouseover,mouseout事件,采用jquery的on方法。大致如下

$(document).on("mouseover","#A",function(){      $(this).find("#B").css({"display":"block"});      $.get("***",null,function(data){         $(this).find("#B").html(data);      })});$(document).on("mouseout","#A",function(){       $(this).find("#B").css({"display":"none"});});
显示大概是下图这样

  可是TMD我发现我鼠标移动到A上出现B后,鼠标在两者间滑动,网络在不停的请求子元素的数据,也就是说在不停的触发A元素的mouseover事件,然后页面中就卡几下。

当时项目发布比较急,就没管,后来周末一大早,心头很闷,大冬天爬起来洗个澡打开电脑就开始研究这个问题。


第一步:

代码:

<script type="text/javascript" src="jquery.comjquery-1.10.2.min.js"></script><style>#father{width:200px;height:200px;background-color:red;position:relative;}#child{display:none;position:absolute;left:0;top:199px;width:100px;height:100px;background-color:yellow;}#record{width:300px;height:100px;border:1px solid blue;position:absolute;right:0;top:0;}</style><script>$(document).on("mouseover","#father",function(e){$("#record").append("father mouseover</br>");$(this).find("div").css({"display":"block"});});$(document).on("mouseout","#father",function(e){$("#record").append("father mouseout</br>");$(this).find("div").css({"display":"none"});});</script><div id="father"><div id="child" ></div></div><div id="record" ></div>

我的鼠标从father元素滑入,出现了child元素,再从father元素滑到child元素中,出现如下情况


也就是说father元素先触发mouseover事件,当鼠标进入child元素后触发了mouseout事件,并且再次触发了mouseover事件。

这种情况只有一种解释,就是从father滑入child时,father元素触发了mouseout事件的,进入child元素触发了child的mouseover事件,并且通过事件冒泡,进而触发了father元素的mouseover事件。

第二步:

为了证实上述的解释,接下来做另一个实验。

<script type="text/javascript" src="jquery.comjquery-1.10.2.min.js"></script><style>#father{width:200px;height:200px;background-color:red;position:relative;}#child{display:none;position:absolute;left:0;top:199px;width:100px;height:100px;background-color:yellow;}#record{width:300px;height:100px;border:1px solid blue;position:absolute;right:0;top:0;}</style><script>$(document).on("mouseover","#father",function(e){$("#record").append("father mouseover</br>");$(this).find("div").css({"display":"block"});});$(document).on("mouseout","#child",function(e){e.stopPropagation();$("#record").append("child mouseout</br>");});$(document).on("mouseover","#child",function(e){e.stopPropagation();$("#record").append("child mouseover</br>");});$(document).on("mouseout","#father",function(e){$("#record").append("father mouseout</br>");$(this).find("div").css({"display":"none"});});</script><div id="father"><div id="child" ></div></div><div id="record" ></div>

出现如下记录


动作和第一步中的动作一致,但是我使用了阻止冒泡,所以father元素就没有触发了第二次的mouseover事件,并且此时child元素由于father元素触发了mouseout事件将child的display设为none,并且在child触发了mouseover事件时没有冒泡触发father的此事件,所以没有将child的display设为block,所以child不再显示了。

也就是说当鼠标在father和child之间滑动时,是通过father不断的触发mouseover事件才使得child元素一直显示,其实是child一直在循环消失又再显示的过程,肉眼无法分辨,所以看到child会一直显示。

是不是这样呢?我们接着看

第三步:

代码:

<script type="text/javascript" src="jquery.comjquery-1.10.2.min.js"></script><style>#father{width:200px;height:200px;background-color:red;position:relative;}#child{display:none;position:absolute;left:0;top:199px;width:100px;height:100px;background-color:yellow;}#record{width:300px;height:100px;border:1px solid blue;position:absolute;right:0;top:0;}</style><script>$(document).on("mouseover","#father",function(e){$("#record").append("father mouseover</br>");$(this).find("div").css({"display":"block"});});$(document).on("mouseout","#child",function(e){//e.stopPropagation();$("#record").append("child mouseout</br>");});$(document).on("mouseover","#child",function(e){//e.stopPropagation();$("#record").append("child mouseover</br>");});$(document).on("mouseout","#father",function(e){$("#record").append("father mouseout</br>");$(this).find("div").css({"display":"none"});});</script><div id="father"><div id="child" ></div></div><div id="record" ></div>

记录如下:


果然,我的动作依然是从father滑入,然后向下滑入到child元素内,触发的事件如上图所示。


到这里我已经明白我项目中的那个问题产生的原因,但是怎么解决呢,我希望在A和B元素间滑动时不要再重复请求服务端数据,可是A的mouseover事件在一直触发,怎么办呢?突然我想起了target....

第三步:


代码:

<script type="text/javascript" src="jquery.comjquery-1.10.2.min.js"></script><style>#father{width:200px;height:200px;background-color:red;position:relative;}#child{display:none;position:absolute;left:0;top:199px;width:100px;height:100px;background-color:yellow;}#record{width:300px;height:100px;border:1px solid blue;position:absolute;right:0;top:0;}</style><script>$(document).on("mouseover","#father",function(e){$("#record").append("father mouseover,target:"+e.target.id+"</br>");$(this).find("div").css({"display":"block"});});$(document).on("mouseout","#child",function(e){//e.stopPropagation();$("#record").append("child mouseout,target:"+e.target.id+"</br>");});$(document).on("mouseover","#child",function(e){//e.stopPropagation();$("#record").append("child mouseover,target:"+e.target.id+"</br>");});$(document).on("mouseout","#father",function(e){$("#record").append("father mouseout,target:"+e.target.id+"</br>");$(this).find("div").css({"display":"none"});});</script><div id="father"><div id="child" ></div></div><div id="record" ></div>

同样的鼠标移动操作,产生结果如下:


target是某次事件触发的原始元素,也就是第一个触发此事件的元素,然后冒泡,引起上级元素触发此事件。

上图中清晰记录了事件触发的源头。“father mouseover,target:child”这条记录说明father的mouseover事件触发的源头是child。

那么在我的项目中的那个问题,我可通过触发事件的源头来决定是否请求服务端的数据,修改大致如下:

$(document).on("mouseover","#A",function(e){      $(this).find("#B").css({"display":"block"});  var flag=parseInt($("#C").val());  if(e.target.id=="A"){  $.get("***",null,function(data){ $(this).find("#B").html(data);  })  }});$(document).on("mouseout","#A",function(e){       $(this).find("#B").css({"display":"none"});   $("#C").val("true");});









2 0