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

移动端响应式导航父链接不可点击及子菜单切换需求求助

解决方案

核心问题分析

原代码中给带子女菜单的父级链接绑定了touchstart事件并调用event.preventDefault(),直接阻止了链接跳转;同时未单独区分"+/-"按钮的交互逻辑,导致点击父链接任意位置都会触发子菜单切换,而非跳转。

修改步骤

1. 调整JavaScript逻辑(navigation.js)

替换原有linksWithChildren事件绑定和toggleFocus函数,单独监听"+/-"按钮的点击事件,保留父链接跳转功能:

/**
 * File navigation.js.
 *
 * Handles toggling the navigation menu for small screens and enables TAB key
 * navigation support for dropdown menus.
 */
( function() {
    const siteNavigation = document.getElementById( 'site-navigation' );

    // Return early if the navigation doesn't exist.
    if ( ! siteNavigation ) {
        return;
    }

    const button = siteNavigation.getElementsByTagName( 'button' )[ 0 ];

    // Return early if the button doesn't exist.
    if ( 'undefined' === typeof button ) {
        return;
    }

    const menu = siteNavigation.getElementsByTagName( 'ul' )[ 0 ];

    // Hide menu toggle button if menu is empty and return early.
    if ( 'undefined' === typeof menu ) {
        button.style.display = 'none';
        return;
    }

    if ( ! menu.classList.contains( 'nav-menu' ) ) {
        menu.classList.add( 'nav-menu' );
    }

    // Toggle the .toggled class and the aria-expanded value each time the button is clicked.
    button.addEventListener( 'click', function() {
        siteNavigation.classList.toggle( 'toggled' );

        if ( button.getAttribute( 'aria-expanded' ) === 'true' ) {
            button.setAttribute( 'aria-expanded', 'false' );
        } else {
            button.setAttribute( 'aria-expanded', 'true' );
        }
    } );

    // Remove the .toggled class and set aria-expanded to false when the user clicks outside the navigation.
    document.addEventListener( 'click', function( event ) {
        const isClickInside = siteNavigation.contains( event.target );

        if ( ! isClickInside ) {
            siteNavigation.classList.remove( 'toggled' );
            button.setAttribute( 'aria-expanded', 'false' );
        }
    } );

    // Get all the link elements within the menu.
    const links = menu.getElementsByTagName( 'a' );

    // Toggle focus each time a menu link is focused or blurred.
    for ( const link of links ) {
        link.addEventListener( 'focus', toggleFocus, true );
        link.addEventListener( 'blur', toggleFocus, true );
    }

    // ------------- 新增/修改部分 -------------
    // 获取所有"+/-"按钮
    const toggleButtons = menu.querySelectorAll( '.plus-minus' );

    // 为每个"+/-"按钮绑定点击事件
    for ( const btn of toggleButtons ) {
        btn.addEventListener( 'click', function( e ) {
            // 阻止事件冒泡与默认行为,避免触发父链接跳转
            e.preventDefault();
            e.stopPropagation();

            const parentLi = this.closest( '.menu-item' );
            const subMenu = parentLi.querySelector( '.sub-menu' );
            
            // 切换子菜单显示状态
            parentLi.classList.toggle( 'focus' );
            // 切换"+/-"文本
            this.textContent = this.textContent === '+' ? '-' : '+';
            
            // 无障碍优化:更新aria-expanded属性
            const parentLink = parentLi.querySelector( 'a' );
            const isExpanded = parentLink.getAttribute( 'aria-expanded' ) === 'true';
            parentLink.setAttribute( 'aria-expanded', !isExpanded );
        } );

        // 移动端触摸事件适配
        btn.addEventListener( 'touchstart', function( e ) {
            e.preventDefault();
            this.click();
        }, false );
    }

    // 移除原有的linksWithChildren触摸事件绑定,避免阻止父链接跳转
    // ------------- 新增/修改结束 -------------

    /**
     * Sets or removes .focus class on an element.
     */
    function toggleFocus() {
        if ( event.type === 'focus' || event.type === 'blur' ) {
            let self = this;
            // Move up through the ancestors of the current link until we hit .nav-menu.
            while ( ! self.classList.contains( 'nav-menu' ) ) {
                // On li elements toggle the class .focus.
                if ( 'li' === self.tagName.toLowerCase() ) {
                    self.classList.toggle( 'focus' );
                }
                self = self.parentNode;
            }
        }
    }
}() );

2. 补充CSS样式(确保子菜单切换生效)

在移动端媒体查询中添加以下样式,控制子菜单的显示/隐藏:

@media (max-width: 768px) {
    .main-navigation .sub-menu {
        display: none;
        padding-left: 1rem;
        /* 可根据需求调整子菜单样式 */
    }
    .main-navigation .menu-item.focus .sub-menu {
        display: block;
    }
    .plus-minus {
        cursor: pointer;
        margin-left: 0.5rem;
        user-select: none;
        /* 可根据需求调整按钮样式 */
    }
}

关键改进点

  • 单独将"+/-"作为子菜单触发按钮,父链接点击可正常跳转
  • 点击"+/-"时自动切换文本符号,同步控制子菜单显示状态
  • 移除原代码中阻止父链接跳转的逻辑,仅在点击按钮时阻止事件冒泡
  • 保留原有键盘导航支持,确保无障碍访问体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 11:37:01