JS当中,mouseover和mouseout多次触发事件,不光是冒泡会产生,就是不冒泡,在一定条件下 ,也会产生多次触发事件;

例如下面的结构的情况下,我在class="ceng_up feature_tips"这个层上加这两个事件,就会多次触发mouseover和mouseout而不断的交替事件。

    <div id="tip_popu">
<!--浮动层-->
<div class="ceng_up feature_tips" style="top:4px; left:9px;">
<div class="top_feature"><div class="inner_text"><img src="/themes/default/images/icon.gif"><a href="#" class="em_a">武林英雄</a></div><div class="jishu">5426</div></div>
<div class="xiaceng">
<a class="c_1" href="#"></a>
<a class="c_2" href="#"></a>
<a class="c_3" href="#" title="活动公告"></a>
<div class="benzhou">本周<font color="#FF0000">+5%</font></div>
</div>
</div>
<div style="top:35px; left:239px; " class="ceng_down feature_tips">
<div class="top_feature"><div class="inner_text"><img src="/themes/default/images/icon.gif"><a href="#" class="em_a">武林英雄</a></div><div class="jishu">5426</div></div>
<div class="xiaceng">
<a href="#" class="c_1"></a>
<a href="#" class="c_2"></a>
<a title="活动公告" href="#" class="c_3"></a>
<div class="benzhou">本周<font color="#3A9B00">-9%</font></div>
</div>
</div>
</div>

开始是搞了好久,都没有找到适合的方法处理这个问题,最后终于在一个BLOG上看到这样的一个说法,终于把这个问题解决了;

下面是那个BLOG的原话,哥们直接复制过来了,加的颜色区分一下:

在用 到mouseover和mouseout事件来作为事件触发的条件,但是如果我们用做触发的元素内部有其他的元素的时候当鼠标移上的时候会反复的触发 mouseover和mouseout事件。因为内部元素在鼠标移上的时候会向它的父对象派发事件,所以外面元素相当于也触发了mouseover 事件。

为了阻止 mouseover和mouseout的反复触发,这里要用到event对象的一个属性relatedTarget,这个属性就是用来判断 mouseover和mouseout事件目标节点的相关节点的属性。简单的来说就是当触发mouseover事件时,relatedTarget属性代 表的就是鼠标刚刚离开的那个节点,当触发mouseout事件时它代表的是鼠标移向的那个对象。由于MSIE不支持这个属性,不过它有代替的属性,分别是 fromElement和toElement。

有了这个属性,我们就能够清楚的知道我们的鼠标是从哪个对象移过来,又是要移动到哪里去了。这样我们就能够通过判断这个相关联的对象是否在我们要触发事件的对象的内部,或者是不是就是这个对象本身。通过这个判断我们就能够合理的选择是否真的要触发事件。

这里我们还用到了一个用于检查一个对象是否包含在另外一个对象中的方法,contains方法。MSIE和FireFox分别提供了检查的方法,这里封装了一个函数。

function contains(parentNode, childNode) {
if (parentNode.contains) {
return parentNode != childNode && parentNode.contains(childNode);
} else {
return !!(parentNode.compareDocumentPosition(childNode) & 16);
}
}

这个函数用于检查一个对象是否被包含在我们的触发对象里面。

下面就是我们的重点了,我封装了一个用于检查鼠标是否真正从外部移入或者移出对象的函数checkHover(e,target),这个函数需要传入当前的事件对象和目标对象。

function checkHover(e,target){
if (getEvent(e).type=="mouseover") {
return !contains(target,getEvent(e).relatedTarget||getEvent(e).fromElement) && !((getEvent(e).relatedTarget||getEvent(e).fromElement)===target);
} else {
return !contains(target,getEvent(e).relatedTarget||getEvent(e).toElement) && !((getEvent(e).relatedTarget||getEvent(e).toElement)===target);
}
}function getEvent(e){
return e||window.event;
}

函数里面用到的getEvent()函数用于在MSIE或者FF下返回一个可用的event对象,这里你可以自己封装成别的函数。

函数的逻辑很简单,首先判断事件的类型,这个主要是为了迁就MSIE,当是 mouseover的时候relatedTarget在MSIE下应该是 fromElement,而mouseout则应该返回toElement,当然在FF下面就好办了,都是同一个属性relatedTarget。首先判 断我们的relatedTarget是否在目标对象的内部,如果是的话则直接返回假如果不在内部的话则判断是否是目标对象本身,如果是的话返回假,要是两 种情况都不成立则返回真。

到这里我们的主要工作做完了,有了这个函数我们在进行编程的时候只要在mouseover或者mouseout事件内部先检查一下,再进行下一步操作就能轻松实现hover的效果。

myElement.onmouseover=function(e){
if(checkHover(e,this)){
do someting...
}
}
myElement.onmouseout=function(e){
if(checkHover(e,this)){
do someting...
}
}

下面的代码,则是哥们自己写的代码部分,也贴出来,供大家参考(基于jquery):

    //取得当前窗口的事件
var e = window.event;
$('.con_yx ul li img').live(
'mouseover',
function(e) {
if(checkHover(e,this)){
var con_yx = $('.con_yx');
var index = con_yx.index($(this).parent().parent().parent());// 100px;
$('#index_val').val(index);
var currentspan = $(this).parent().find('span');// down
var position = $(this).offset();
if (currentspan.hasClass('up')) {
$(this).parent().find('img,.em_a').clone().appendTo('.ceng_up .inner_text');
$('.ceng_up').css('top', (position.top - 5));
$('.ceng_up').css('left', (position.left - 5));
$('.ceng_up').css('z-index',9999);
$('.ceng_down').hide();
$('.ceng_up').show();
} else {
$(this).parent().find('img,.em_a').clone().appendTo('.ceng_down .inner_text');
$('.ceng_down').css('top', (position.top - 5));
$('.ceng_down').css('left', (position.left - 5));
$('.ceng_down').css('z-index',9999);
$('.ceng_up').hide();
$('.ceng_down').show();
}
}
});
//鼠标移除层区域后,触发mouseout事件,把整个层隐藏
$('.ceng_up,.ceng_down').live('mouseout', function(e) {
if(checkHover(e,this)){
$(this).find('.inner_text').html('');
$(this).hide();
}
}); /**
* 下面是一些基础函数,解决mouseover与mouserout事件不停切换的问题(问题不是由冒泡产生的)
*/
function checkHover(e, target) {
if (getEvent(e).type == "mouseover") {
return !contains(target, getEvent(e).relatedTarget
|| getEvent(e).fromElement)
&& !((getEvent(e).relatedTarget || getEvent(e).fromElement) === target);
} else {
return !contains(target, getEvent(e).relatedTarget
|| getEvent(e).toElement)
&& !((getEvent(e).relatedTarget || getEvent(e).toElement) === target);
}
} function contains(parentNode, childNode) {
if (parentNode.contains) {
return parentNode != childNode && parentNode.contains(childNode);
} else {
return !!(parentNode.compareDocumentPosition(childNode) & 16);
}
}
//取得当前window对象的事件
function getEvent(e) {
return e || window.event;
}

js当中mouseover和mouseout多次触发(非冒泡)的更多相关文章

  1. mouseover和mouseout多次触发解决方法(兼容ie和firefox)(转)

    在用到mouseover和mouseout事件来作为事件触发的条件,但是如果我们用做触发的元素内部有其他的元素的时候当鼠标移上的时候会反复的触发mouseover和mouseout事件,如导致菜单闪烁 ...

  2. jq:mouseover和mouseout多次触发解决办法

    区别: mouseover与mouseenter 不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件. 只有在鼠标指针穿过被选元素时,才会触发 mouseenter 事件. mou ...

  3. mouseover和mouseout事件在鼠标经过子元素时也会触发

    JavaScript的mouseover和mouseout事件,在绑定元素内部有子元素的情况下, 经过绑定元素时会多次触发mouseover和mouseout事件. jQuery解决办法: jquer ...

  4. mouseover和mouseout、mouseenter和mouseleave

    又一个傻傻分不清楚的东东~ 现实真是一个问题天天有的世界~本以为我对js中的事件还是比较了解的,对于早就接触的mouse事件,更是觉得得心应手了~但是现实却给了我一记重拳! 我自身工作中遇到的犯二的故 ...

  5. jQuery-使用hover(fn,fn)函数监听mouseover和mouseout两个事件

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  6. jQuery mouseove和mouseout事件不断触发

    关于锋利的jQuery第三章结尾提示图片效果(鼠标放在图片上会出现一个大图跟随鼠标移动)实现时mouseove和mouseout事件不断触发的问题 html <ul class="bo ...

  7. mouseover和mouseout事件引发的BUG-解决方法

    mouseover和mouseout引发的BUG原由 当给一个元素添加mouseover或mouseout事件,这个元素还有子元素. 由于子元素的事件冒泡,鼠标移入或移出子元素都会触发事件. 解决的方 ...

  8. 鼠标 mouseover和mouseout事件

    在div内想实现鼠标移入移出效果,最开始的时候是用了jquery的mouseout和mouseover事件来实现的, $('.product).mouseover(function(){ …… }). ...

  9. mouseover、mouseout,mouseenter、mouseleave区别

    心情压抑的一天,我想好好的. mouseover与mouseenter 不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件. 只有在鼠标指针穿过被选元素时,才会触发 mouseen ...

随机推荐

  1. LeetCode初级算法(数组)解答

    这里记录了LeetCode初级算法中数组的一些题目: 加一 本来想先转成整数,加1后再转回去:耽美想到测试的例子考虑到了这个方法的笨重,所以int类型超了最大范围65536,导致程序出错. class ...

  2. LDAP相关操作注意事项

    lc.Modify(entry.DN, new LdapModification(LdapModification.REPLACE, new LdapAttribute("mDBUseDef ...

  3. Caused by: MetaException(message:Hive Schema version 2.1.0 does not match metastore's schema version 1.2.0 Metastore is not upgraded or corrupt)

    解决方案汇总: ()删除HDFS上的hive数据与hive数据库 hadoop fs -rm -r -f /tmp/hive hadoop fs -rm -r -f /user/hive ()删除My ...

  4. android 缓存路径

    用程序在运行的过程中如果需要向手机上保存数据,一般是把数据保存在SDcard中的.大部分应用是直接在SDCard的根目录下创建一个文件夹,然后把数据保存在该文件夹中.这样当该应用被卸载后,这些数据还保 ...

  5. deep copy and shallow copy

    链接A:浅拷贝就是成员数据之间的一一赋值:把值赋给一一赋给要拷贝的值.但是可能会有这样的情况:对象还包含资源,这里的资源可以值堆资源,或者一个文件..当值拷贝的时候,两个对象就有用共同的资源,同时对资 ...

  6. JavaScript 浮点数处理

    众所周知,JavaScript 浮点数运算时经常遇到会 0.000000001 和 0.999999999 这样奇怪的结果,如 0.1+0.2=0.30000000000000004.1-0.9=0. ...

  7. (三)Redis两种持久化方案

    Redis的持久化策略:2种 RDB方式的持久化是通过快照(snapshotting)完成的,当符合一定条件时Redis会自动将内存中的数据进行快照并持久化到硬盘.RDB是Redis默认采用的持久化方 ...

  8. 一个简单的CI分页类

    [php] view plaincopy <span style="font-size:16px;">/** * * 关于 页码有效性的判断需要加在 控制器中判断,即当 ...

  9. 服务器端控件的"客户端"

    控件的服务端ID和客户端ID 比如一个ID为TextBox1的服务器端控件,在客户端访问该控件的DOM元素时 错误: var txtbox=document.getElementByID(" ...

  10. struts2 第二天

    3.自动装配  零散属性:Action类中两个成员变量的名称和页面上表单元素name属性值保持一致.      规则:约定优于配置.  领域模型:两种配置    public class FirstA ...