移动端响应式导航父链接不可点击及子菜单切换需求求助
解决方案
核心问题分析
原代码中给带子女菜单的父级链接绑定了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
相关产品推荐
相关产品推荐

