You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用jQuery关闭多级菜单中当前点击分支外的展开菜单?

多级菜单jQuery开合逻辑问题

我正在用CSS Flex制作多级菜单,通过jQuery实现菜单及子菜单的开合功能,需求逻辑如下:

  • 点击「Contact」展开其菜单
  • 点击「A propo」时,「Contact」需关闭
  • 点击一级子菜单(Item 1.2),父级菜单保持展开
  • 点击二级子菜单(Item 1.2.3),其所有直接父级ul不关闭
  • 再次点击「Contact」时,「A propo」的所有菜单及子菜单需关闭

当前开合菜单的脚本可正常运行,但缺少关闭其他分支的逻辑:

( function( $ ) {
    $( '.dropdown-toggle' ).click( function( e ) {
        var _this = $( this );
        e.preventDefault();
        _this.toggleClass( 'toggled-on' );
        _this.find('.fa').toggleClass( 'fa-angle-down fa-angle-up');
        _this.parent().next( '.sub-menu' ).toggleClass( 'toggled-on' );
        _this.attr( 'aria-expanded', _this.attr( 'aria-expanded' ) === 'false' ? 'true' : 'false' );
         // 需添加关闭其他菜单的逻辑
    } );
})( jQuery );

我遇到的具体疑问:

  1. 如何从_this定位到顶级的li.hasChildren?
  2. 如何检查顶级li之外的其他li.hasChildren分支?
  3. 如何关闭当前点击分支外的所有ul.toggled-on元素?

我试过用parentUntil()方法,但它遇到第一个li.hasChildren就停止了,无法定位到顶级li。注:菜单展开时对应ul会添加ul.toggled-on类,关闭时需调用removeClass('toggled-on')。

菜单的HTML结构如下:

<nav class="e-panel e-panel-row" role="navigation" aria-label="Main navigation">
    <ul class="e-justify-content-space-beween bg-black">
        <li class="hasChildren">
            <div>
                <a href="#">A propo</a>
                <a href="#" class="dropdown-toggle" aria-expanded="false">
                    [12]
                    <i class="fa fa-angle-down"></i>
                </a>
            </div>
            <ul class="sub-menu" role="group">
                <li>
                    <div>
                        <a class="link" href="#">Item 1.1</a>
                    </div>
                </li>
                <li class="hasChildren">
                    <div>
                        <a href="#">Item 1.2</a>
                        <a href="#" class="dropdown-toggle" aria-expanded="false">
                            [1]
                            <i class="fa fa-angle-down"></i>
                        </a>
                    </div>
                    <ul class="sub-menu" role="group">
                        <li>
                            <div>
                                <a href="#">Item 1.2.1</a>
                            </div>
                        </li>
                        <li>
                            <div>
                                <a href="#">Item 1.2.2</a>
                            </div>
                        </li>
                        <li class="hasChildren">
                            <div>
                                <a href="#">Item 1.2.3</a>
                                <a href="#" class="dropdown-toggle" aria-expanded="false">
                                    [1]
                                    <i class="fa fa-angle-down"></i>
                                </a>
                            </div>
                            <ul class="sub-menu">
                                <li><div><a href="#">Item 1.2.3.1</a></div></li>
                                <li><div><a href="#">Item 1.2.3.2</a></div></li>
                                <li><div><a href="#">Item 1.2.3.3</a></div></li>
                            </ul>
                        </li>
                    </ul>
                </li>
                <li>
                    <div>
                    <a href="#">Item 333333</a>
                    </div>
                </li>
            </ul>
        </li>    
        <li>
            <div>
                <a href="#">Team</a>
            </div>
        </li>
        <li class="hasChildren">
            <div>
                <a href="#">Contact</a>
                <a href="#" class="dropdown-toggle" aria-expanded="false">
                            [13]
                    <i class="fa fa-angle-down"></i>
                </a>
            </div>
            <ul class="sub-menu" role="group">
                <li>
                    <div>
                        <a href="#">Adresse</a>
                    </div>
                </li>
                <li>
                    <div>
                        <a href="#">Téléphone</a>
                        </div>
                    </li>
                <li>
                    <div>
                        <a href="#">e-mail</a>
                    </div>
                </li>
            </ul>
        </li>
        <li>
            <div>
                <a href="#">Nos cours</a>
            </div>
        </li>
        <li>
            <div>
                <a href="#">Menu 3</a>
            </div>
        </li>
        <li>
            <div>
                <a href="#">Encore un beau menu 4</a>
            </div>
        </li>
        <li>
            <div>
                <a href="#">Contact</a>
            </div>
        </li>
    </ul>
</nav>

核心问题:如何筛选并关闭当前点击分支外的所有ul.toggled-on元素?


解决方案

要实现需求,我们可以按以下步骤修改代码:

  1. 定位当前分支的所有父级及自身菜单:从点击的dropdown-toggle出发,找到所有属于当前分支的ul.sub-menu和对应的dropdown-toggle按钮。
  2. 关闭其他分支的所有展开项:选中所有ul.toggled-on,排除当前分支内的元素,然后统一关闭,并重置对应的按钮状态。

修改后的完整代码如下:

( function( $ ) {
    $( '.dropdown-toggle' ).click( function( e ) {
        var _this = $( this );
        e.preventDefault();
        
        // 处理当前菜单的开合状态
        var currentSubmenu = _this.parent().next( '.sub-menu' );
        var isExpanding = !_this.hasClass( 'toggled-on' );
        
        _this.toggleClass( 'toggled-on' );
        _this.find('.fa').toggleClass( 'fa-angle-down fa-angle-up');
        currentSubmenu.toggleClass( 'toggled-on' );
        _this.attr( 'aria-expanded', isExpanding ? 'true' : 'false' );
        
        // 获取当前分支的所有菜单元素(包括父级子菜单和当前子菜单)
        var currentBranch = _this.parentsUntil( '.e-justify-content-space-beween', '.sub-menu' )
                                .addBack()
                                .add( currentSubmenu );
        
        // 关闭所有非当前分支的展开菜单
        $('.sub-menu.toggled-on').not(currentBranch).each(function() {
            var $submenu = $(this);
            $submenu.removeClass('toggled-on');
            
            // 重置对应toggle按钮的状态
            var $toggle = $submenu.prev('div').find('.dropdown-toggle');
            $toggle.removeClass('toggled-on');
            $toggle.find('.fa').removeClass('fa-angle-up').addClass('fa-angle-down');
            $toggle.attr('aria-expanded', 'false');
        });
        
        // 如果是收起顶级菜单,同时关闭其下所有子菜单
        var topLevelLi = _this.closest('.hasChildren');
        if (!isExpanding && topLevelLi.parent().hasClass('e-justify-content-space-beween')) {
            topLevelLi.find('.sub-menu.toggled-on').removeClass('toggled-on');
            topLevelLi.find('.dropdown-toggle.toggled-on').each(function() {
                var $toggle = $(this);
                $toggle.removeClass('toggled-on');
                $toggle.find('.fa').removeClass('fa-angle-up').addClass('fa-angle-down');
                $toggle.attr('aria-expanded', 'false');
            });
        }
    } );
})( jQuery );

代码说明:

  • 定位当前分支:用parentsUntil('.e-justify-content-space-beween', '.sub-menu')找到当前点击按钮所在的所有父级子菜单,结合当前子菜单组成当前分支的元素集合,避免误关同分支内的菜单。
  • 关闭其他分支:通过.not(currentBranch)排除当前分支,遍历剩余展开菜单,统一重置类和属性状态。
  • 顶级菜单收起逻辑:判断当前点击的是否为顶级菜单按钮,若为收起操作,同时关闭其下所有展开的子菜单,满足需求中的第5点。

内容的提问来源于stack exchange,提问作者pierrot10

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 04:05:11