slideUp()期间stop(true).slideDown()的问题是一个jquery错误



我有一个折叠菜单的代码粘贴在下面,或者在jsfiddle上看到它。

问题是,当子菜单处于向上滑动状态,再次单击时,它会停止,但不会向后设置动画(相反,子菜单会跳出,但其容器保持当前高度-jQuery 2.0.0.b1没有跳过)。在Firefox和Chrome中进行了测试,结果相同。

这是一个jQuery错误,还是只有我?

更新:我已经为jQuery提交了一份错误报告,因为我认为这是一个jQuery错误。

更新2:请参阅Brad M对该行为的解释(但我仍然认为这是jQuery的一个问题,需要在内部解决)。

HTML

<ul>
    <li><a href="#">Menu1</a></li>
    <li class="opened"><a href="#">Submenus 1</a>
        <ul class="submenu">
            <li><a href="#">submenu1-1</a></li>
            <li><a href="#">submenu1-2</a></li>
        </ul></li>
    <li class="closed"><a href="#">Submenus 2</a>
        <ul class="submenu">
            <li><a href="#">submenu2-1</a></li>
            <li><a href="#">submenu2-2</a></li>
        </ul></li>
    <li><a href="#">Menu4</a>
    </li>
</ul>

Javascript

var initMenu = function() {
    $("li.closed > ul.submenu").css("display", "none");
    var toggleMenu = function(li) {
        if (li.hasClass("opened") || li.hasClass("inslidedown")) {
            li.removeClass("opened inslidedown").addClass("inslideup").find("ul").first().stop(true).slideUp({
                duration: 1000,
                complete: function() {
                    li.addClass("closed").removeClass("inslideup");
                }
            });
        }
        else if (li.hasClass("closed") || li.hasClass("inslideup")) {
            li.removeClass("closed inslideup").addClass("inslidedown").find("ul").first().stop(true).slideDown({
                duration: 1000,
                complete: function() {
                    li.addClass("opened").removeClass("inslidedown");
                }
            });
        }
    };
    $("ul").on("click", "li.opened a, li.closed a, li.inslideup a, li.inslidedown a", function(e) {
        e.preventDefault();
        toggleMenu($(this).closest("li"));
    });
};
$(document).ready(function() {
    initMenu();
});

.slideDown()不工作的原因是元素的显示设置为"block",而.slideDown()通常用于在显示为"none"的元素上调用。在else-if语句中的ul元素上包含.hide(),以获得您想要的行为。

li
    .removeClass("closed inslideup")
    .addClass("inslidedown")
    .find("ul")
    .first()
    .hide()   //   <----
    .stop(true)
    .slideDown();

这是我的版本:http://jsfiddle.net/RF3xK/4/

Javascript:

$(document).ready(function() {
rotator($('#quotes .textItem:first'));
function rotator(elem) {
    elem.slideDown(800, function(){
      var me = $(this),
          next = me.next(),
          prev = me.prev();
      if (!next.length) {
          next = $('.textItem').first();
          next.insertAfter(me);
      }
      rotator(next);
    }).delay(800).slideUp(800);
}
});

CSS:

#quotes { background: #eee;}
#quotes .textItem { display: none; }

请注意,我将.hide()替换为document.ready事件上的那些元素,这是不必要的javascript,你可以像我一样用css来做,js方法的另一个问题是,在很短的一段时间内,它会出现和消失,因为你必须等到所有文档加载后才能隐藏这些元素。

基本上,你应该检查<ul>下的所有<li>节点是否都有css类,比如关闭打开,你可以使用jQuery选择器来实现这一点。

这里有一个快速而肮脏的解决方法,你绝对可以将其重新考虑到更好的逻辑中。

if ($('li[class~="opened"]').length > 0 || $('li[class~="inslidedown"]').length > 0) {
    ...
}
else if ($('li[class~="closed"]').length > 0 || $('li[class~="inslideup"]').length > 0) {
    ...
}

第一个问题是由于您使用了.stop()

根据jquery文档,

.stop([clearQueue][,jumpToEnd])

clearQueue类型:布尔一个布尔值,指示是否也删除排队的动画。默认为false。

跳转到结束类型:布尔指示是否立即完成当前动画的布尔值。默认为false。

通常,在处理动画时,您希望使用.stop(false,true)。

至于您的第二个问题,原因是以下jquery/css。

li.removeClass("closed-inslidup")

li.closed>ul{display:none;}

当您移除"closed"类时,ul元素的显示会被设置回默认的"block",因此它会立即显示。向下滑动的动画不会出现,因为元素已经显示(但回调仍在执行)。

目前,我使用的解决方法只是在滑动动画进行时忽略单击事件。刚刚在第23行从.on()的选择器筛选参数中删除了li.inslideup a, li.inslidedown a选择器(在jQuery被修复的情况下,保留其他代码不变,但它可以被简化)。

解决方法在jsfiddle上。

相关内容

最新更新