js当中mouseover和mouseout多次触发(非冒泡)
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多次触发(非冒泡)的更多相关文章
- mouseover和mouseout多次触发解决方法(兼容ie和firefox)(转)
在用到mouseover和mouseout事件来作为事件触发的条件,但是如果我们用做触发的元素内部有其他的元素的时候当鼠标移上的时候会反复的触发mouseover和mouseout事件,如导致菜单闪烁 ...
- jq:mouseover和mouseout多次触发解决办法
区别: mouseover与mouseenter 不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件. 只有在鼠标指针穿过被选元素时,才会触发 mouseenter 事件. mou ...
- mouseover和mouseout事件在鼠标经过子元素时也会触发
JavaScript的mouseover和mouseout事件,在绑定元素内部有子元素的情况下, 经过绑定元素时会多次触发mouseover和mouseout事件. jQuery解决办法: jquer ...
- mouseover和mouseout、mouseenter和mouseleave
又一个傻傻分不清楚的东东~ 现实真是一个问题天天有的世界~本以为我对js中的事件还是比较了解的,对于早就接触的mouse事件,更是觉得得心应手了~但是现实却给了我一记重拳! 我自身工作中遇到的犯二的故 ...
- jQuery-使用hover(fn,fn)函数监听mouseover和mouseout两个事件
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- jQuery mouseove和mouseout事件不断触发
关于锋利的jQuery第三章结尾提示图片效果(鼠标放在图片上会出现一个大图跟随鼠标移动)实现时mouseove和mouseout事件不断触发的问题 html <ul class="bo ...
- mouseover和mouseout事件引发的BUG-解决方法
mouseover和mouseout引发的BUG原由 当给一个元素添加mouseover或mouseout事件,这个元素还有子元素. 由于子元素的事件冒泡,鼠标移入或移出子元素都会触发事件. 解决的方 ...
- 鼠标 mouseover和mouseout事件
在div内想实现鼠标移入移出效果,最开始的时候是用了jquery的mouseout和mouseover事件来实现的, $('.product).mouseover(function(){ …… }). ...
- mouseover、mouseout,mouseenter、mouseleave区别
心情压抑的一天,我想好好的. mouseover与mouseenter 不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件. 只有在鼠标指针穿过被选元素时,才会触发 mouseen ...
随机推荐
- Datatable 转换 Dictionary
DataTable dt = new DataTable(); dt.Columns.Add("姓名"); dt.Columns.Add("学号"); dt.R ...
- JMeter - 实时结果 - InfluxDB和Grafana - 第1部分 - 基本设置
概述: 在本文中,我将解释如何使用JMeter + InfluxDB + Grafana获得实时性能测试结果. 请注意,此主题太大,无法涵盖一篇文章中的所有内容.所以,我试图提供与TestAutoma ...
- 分别使用http,express,koa请求第三方接口
今天又再次恶补了一下http的内容,确切地说是node.js里面的http的内容,啊,百度了半天express怎么请求第三方接口,结果发现自己买的入门书籍都有这个内容.舍近求远,我真是醉了.还有百度上 ...
- Java中文编程开发,让Java编写更改复杂
额?what? 在B站无意中看到一张图,无意间已发了自己的好奇,实际上我早就知道Java支持Unicode编码也就是可以使用中文命名规则,但是我们可以包装一下,玩一玩完全使用中文编码也未尝不可,但是经 ...
- MD5WLBUtil
import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; import j ...
- UVALive - 6442
题目链接:https://vjudge.net/contest/241341#problem/I 题目大意:输入t,t组样例,输入n,m,有n个圆槽,m个硬币,接下来m行代表每个硬币所在的位子,要求你 ...
- Murano Weekly Meeting 2015.07.14
会议时间: 2015.07.14 主持人: Kirill Zaitsev, core from Mirantis 会议摘要: 1.periodic nightly builds,然后通过mailin ...
- java中key值可以重复的map:IdentityHashMap
在Java中,有一种key值可以重复的map,就是IdentityHashMap.在IdentityHashMap中,判断两个键值k1和 k2相等的条件是 k1 == k2 .在正常的Map 实现(如 ...
- C# 多线程之线程控制
方案一: 调用线程控制方法.启动:Thread.Start();停止:Thread.Abort();暂停:Thread.Suspend();继续:Thread.Resume(); private vo ...
- [Environment Build] 工作中遇到的关于Git的问题
修改已经提交的commit中的author, commit git commit --amend --author 'Your Name <Your Email>' git commit ...