React移动端导航菜单交互异常求助:需实现初始隐藏、点击显示
问题描述
移动端加载页面时,id为nav-5的菜单默认显示,点击汉堡按钮(navBtn1)后菜单被隐藏,期望实现移动端默认隐藏菜单,点击汉堡按钮切换显示/隐藏。
代码片段
import React from 'react' import Logo1 from "../images/Logo1.png"; import Logo2 from "../images/Logo2.png"; import { GlobalInfo } from "../App"; import "../styles/Nav.css"; import { Link } from "react-router-dom"; function Nav() { const Theme = React.useContext(GlobalInfo) const navFun1 = () => { const x = document.getElementById('navBtn1') const y = document.getElementById('nav-5') console.log("Hello") if (y.style.display == 'block') { y.style.display = 'none' } else { y.style.display = 'block' } } return ( <> <div className={`nav ${Theme.ThemeType === 'light' ? 'nav-dark' : ''}`}> <div className="nav-1"> {Theme.ThemeType != 'light' ? <img src={Logo1} alt="Logo" /> : <img src={Logo2} alt="Logo" />} </div> <div className="nav-2"> <a href="#">Fundrise</a> <a href="#">Invest</a> </div> <div className="nav-3"> <button> Connect Wallet </button> </div> <div className="nav-4"> <button id='navBtn1' onClick={navFun1}> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-list" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z" /> </svg> </button> <div className="nav-5" id='nav-5'> <Link to='dashboard/s2'>Fundrise</Link> <Link to='dashboard/s1'>Invest</Link> <Link to='/'>Connect Wallet</Link> </div> </div> </div> </> ) } export default Nav
问题原因
- 初始样式未正确设置:移动端下
nav-5的默认显示状态由CSS控制,但你未在样式中设置它默认隐藏,导致页面加载时菜单直接显示。 - JS判断逻辑缺陷:
y.style.display仅读取元素的行内样式,而初始时元素的display值来自CSS,并非行内样式,所以初始判断值为空字符串,第一次点击会执行else分支将行内样式设为block——但此时菜单原本就是显示状态,再次点击才会隐藏,和你的期望完全相反。 - 直接操作DOM不符合React规范:React推荐通过状态管理UI变化,直接操作DOM容易导致状态不一致,后期难以维护。
解决方案
方案一:React状态管理(推荐)
通过useState控制菜单显示状态,配合CSS类名实现响应式切换:
import React, { useState } from 'react' import Logo1 from "../images/Logo1.png"; import Logo2 from "../images/Logo2.png"; import { GlobalInfo } from "../App"; import "../styles/Nav.css"; import { Link } from "react-router-dom"; function Nav() { const Theme = React.useContext(GlobalInfo) // 初始状态设为false,即菜单默认隐藏 const [isMenuOpen, setIsMenuOpen] = useState(false) const navFun1 = () => { // 点击按钮切换状态 setIsMenuOpen(!isMenuOpen) } return ( <> <div className={`nav ${Theme.ThemeType === 'light' ? 'nav-dark' : ''}`}> <div className="nav-1"> {Theme.ThemeType !== 'light' ? <img src={Logo1} alt="Logo" /> : <img src={Logo2} alt="Logo" />} </div> <div className="nav-2"> <a href="#">Fundrise</a> <a href="#">Invest</a> </div> <div className="nav-3"> <button>Connect Wallet</button> </div> <div className="nav-4"> <button id='navBtn1' onClick={navFun1}> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-list" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z" /> </svg> </button> {/* 通过状态控制类名,实现显示/隐藏 */} <div className={`nav-5 ${isMenuOpen ? 'show' : 'hidden'}`}> <Link to='dashboard/s2'>Fundrise</Link> <Link to='dashboard/s1'>Invest</Link> <Link to='/'>Connect Wallet</Link> </div> </div> </div> </> ) } export default Nav
然后在Nav.css中添加响应式样式:
/* 移动端断点可根据需求调整 */ @media (max-width: 768px) { /* 桌面端导航隐藏 */ .nav-2, .nav-3 { display: none; } /* 汉堡按钮显示 */ .nav-4 { display: block; } /* 菜单默认隐藏 */ .nav-5.hidden { display: none; } /* 菜单显示状态 */ .nav-5.show { display: block; } } /* 桌面端样式 */ @media (min-width: 769px) { /* 汉堡按钮隐藏 */ .nav-4 { display: none; } /* 桌面端导航显示 */ .nav-2, .nav-3 { display: block; } }
方案二:快速修复原生JS逻辑(不推荐)
如果暂时不想重构代码,可先通过CSS设置菜单默认隐藏,再修改JS判断逻辑:
- 在
Nav.css中添加:
@media (max-width: 768px) { #nav-5 { display: none; } }
- 修改JS点击函数:
const navFun1 = () => { const y = document.getElementById('nav-5') // 获取元素计算后的样式,而非仅行内样式 const computedStyle = window.getComputedStyle(y) if (computedStyle.display === 'block') { y.style.display = 'none' } else { y.style.display = 'block' } }
这样初始时菜单在移动端默认隐藏,点击汉堡按钮可正常切换显示/隐藏状态。
内容的提问来源于stack exchange,提问作者Hammad Saboor
相关产品推荐
相关产品推荐

