防止意外事件在元素上冒泡

时间:2012-08-20 09:34:45

标签: css dom jquery

我正在尝试在列表元素上创建一个简单的悬停效果。但是,当鼠标位于列表项上时,显示的元素之间存在小的差距。这会强制触发事件mouseleave,这是不需要的。

这是fiddle演示。将鼠标悬停在列表项上后,尝试转到小方框。

HTML:

<ul>
    <li>test <div class="block">Block</div></li>
    <li>test2 <div class="block">Block descriptions</div></li>
</ul>​

CSS:

ul { width: 50px; }
ul li { width: 50px; height: 50px; background: #c00; margin: 0 0 10px 0; }
li .block { 
    position: absolute; 
    margin: 0 0 0 70px;
    background: #ddd;
    display: none;
}

JavaScript的:

$("ul li").hover(function() {
    $(this).children(".block").stop().fadeIn();
}, function() {
    $(this).children(".block").stop().fadeOut();
});​

如何防止这种影响?

4 个答案:

答案 0 :(得分:1)

尝试 this demo

$('ul li').on("mouseenter mouseleave",function( e ){
   var $this = $(this);
   if (e.type == 'mouseenter') {
       clearTimeout( $this.data('timeout') );
       $this.find('.block').stop().fadeTo(400,1);
   }else{
       $this.data( 'timeout', setTimeout(function(){
           $this.find('.block').stop().fadeTo(200,0, function(){
             $(this).hide(); 
           });
       },200) );
   }
});

它的作用是:将超时值设置为当前悬停的data元素的li属性,该元素将充当悬停意图,将等待200毫秒mouseenter .block元素保持元素可见。一旦鼠标到达块元素,它将重置超时。

答案 1 :(得分:0)

这样的事情应该有效。可能需要进行一些调整。

http://jsfiddle.net/G5YfR/

var fn = function(elem) {
    $(elem).children(".block").fadeOut();
};
var timeout;
$("ul li").on("mouseenter", function() {
    var that = this;
    clearTimeout(timeout);
    $(this).children(".block").fadeIn();
}).on("mouseleave", function() {
    var that = this;

    timeout = setTimeout(function() {
        fn(that)
    }, 1000);
});

答案 2 :(得分:0)

你有两个附加了鼠标事件处理程序的元素,并且它们相距一段距离放置,所以当鼠标在去往另一个元素的路上留下一个元素时,它会移到两个元素之外,而事件处理程序是再次触发等。

您可以将两个元素放在包装元素中,并将事件处理程序附加到该元素

<ul>
    <li><div>test <div class="block">Block</div></div></li>
    <li><div>test2 <div class="block">Block descriptions</div></div></li>
</ul>​​​​​​​​​​​​​​​​​​​

JS:

$("ul li").on({
    mouseenter: function() {
        $(".block", this).fadeIn();
    },
    mouseleave: function() {
        $(".block", this).fadeOut();
    }
});​

FIDDLE

或者您可以尝试猜测移动鼠标所需的时间并使用一点暂停来伪造它:

var timer;

$("ul li").on({
    mouseenter: function() {
        clearTimeout(timer);
        $(this).children(".block").fadeIn();
    },
    mouseleave: function() {
        var self = this;
        timer = setTimeout(function() {
            $(self).children(".block").fadeOut();
        }, 400);
    }
});​

FIDDLE

答案 3 :(得分:0)

mouseleave事件被触发,因为当你将ty移动到子节点时,你就会离开元素。唯一的解决方案是扩展li元素的宽度。

保持相同的外观,我建议将红色框移动到自己的元素中,例如:

<ul>
    <li>
        <span class="icon">test</span> 
        <span class="block">Block</span>
    </li>
    <li>
        <span class="icon">test2</span> 
        <span class="block">Block descriptions</span>
    </li>
</ul>​

将CSS更改为:

li span {
    display: inline-block;
    vertical-align: middle;
}

li .icon {
    width: 50px; 
    height: 50px; 
    background: #c00;
}

li .block { 
    margin: 0 0 0 70px;
    background: #ddd;
    display: none;
}

li元素扩展到两个孩子:DEMO注意虽然display: inline-block可能在旧的IE版本中不起作用。(根据http://caniuse.com/inline-block应该没问题。)