1

我在下面粘贴了折叠菜单的代码,或者在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();
});
4

5 回答 5

3

原因.slideDown()不起作用是因为元素的显示设置为“块”,并且.slideDown()通常打算在显示为“无”的元素上调用。在 else if 语句中包含.hide()ul 元素以获得您想要的行为。

li
    .removeClass("closed inslideup")
    .addClass("inslidedown")
    .find("ul")
    .first()
    .hide()   //   <----
    .stop(true)
    .slideDown();
于 2013-02-20T02:53:32.227 回答
0

这是我的版本: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 方式的另一个问题是在一小会儿出现和消失因为您必须等到所有文档加载后才能隐藏这些元素。

于 2013-02-20T01:50:45.490 回答
0

基本上你应该检查所有<li>节点下<ul>的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) {
    ...
}
于 2013-02-20T01:54:08.950 回答
0

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

根据 jquery 文档,

.stop( [clearQueue ] [, jumpToEnd ] )

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

jumpToEnd 类型:Boolean 一个布尔值,指示是否立即完成当前动画。默认为假。

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

至于你的第二个问题,原因是由于下面的jquery/css。

li.removeClass("关闭的内联")

li.close > ul { 显示:无;}

当您删除“关闭”类时,ul 元素的显示设置回默认的“块”,因此它会立即显示。不会出现下滑动画,因为元素已经显示(尽管回调仍在执行)。

于 2013-02-20T01:57:35.153 回答
0

现在我正在使用一种解决方法,它在滑动动画正在进行时简单地忽略点击事件。刚刚从第 23 行的选择器过滤参数中删除了li.inslideup a, li.inslidedown a选择.on()器(在 jQuery 得到修复的情况下保持其他代码完整,但可以简化)。

解决方法是在jsfiddle上。

于 2013-02-20T17:37:11.873 回答