React移动端汉堡菜单添加及功能实现求助
React Header组件移动端响应式布局优化方案
需求明确
- 屏幕宽度<768px时,Header左侧的Home/About/Login链接隐藏,替换为汉堡图标
- 点击汉堡图标切换显示/隐藏包含三个链接的移动端菜单
- 搜索、购物车按钮始终保留在Header右侧,不加入汉堡菜单
修改后的完整代码
Header.jsx
import { useEffect, useState, useContext } from "react"; import { useNavigate } from "react-router-dom"; import { TbSearch } from "react-icons/tb"; import { CgShoppingCart } from "react-icons/cg"; import { FaBars, FaTimes } from "react-icons/fa"; import Search from "./Search/Search"; import Cart from "../Cart/Cart"; import { Context } from "../../utils/context"; import "./Header.scss"; const Header = () => { const [scrolled, setScrolled] = useState(false); const [showCart, setShowCart] = useState(false); const [showSearch, setShowSearch] = useState(false); const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const { cartCount } = useContext(Context); const navigate = useNavigate() const handleScroll = () => { const offset = window.scrollY; setScrolled(offset > 200); }; const handleMenuLinkClick = (path) => { navigate(path); setIsMobileMenuOpen(false); }; useEffect(() => { window.addEventListener("scroll", handleScroll); return () => window.removeEventListener("scroll", handleScroll); }, []); return ( <> <header className={`main-header ${scrolled ? 'sticky-header' : ''}`}> <div className="header-content"> <button className="hamburger-btn" onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)} > {isMobileMenuOpen ? <FaTimes /> : <FaBars />} </button> <ul className="left"> <li onClick={() => handleMenuLinkClick("/")}>Home</li> <li onClick={() => handleMenuLinkClick("/about")}>About</li> <li onClick={() => handleMenuLinkClick("/login")}>Login</li> </ul> <div className="center" onClick={() => navigate("/")}>GOLOC.</div> <div className="right"> <TbSearch onClick={() => setShowSearch(true)} /> <span className="cart-icon" onClick={() => setShowCart(true)}> <CgShoppingCart /> {!!cartCount && <span>{cartCount}</span>} </span> </div> </div> <div className={`mobile-menu ${isMobileMenuOpen ? 'open' : ''}`}> <ul> <li onClick={() => handleMenuLinkClick("/")}>Home</li> <li onClick={() => handleMenuLinkClick("/about")}>About</li> <li onClick={() => handleMenuLinkClick("/login")}>Login</li> </ul> </div> </header> {showCart && <Cart setShowCart={setShowCart} />} {showSearch && <Search setShowSearch={setShowSearch} />} </> ); }; export default Header;
Header.scss
@import "../../css-config/mixins.scss"; .main-header { width: 100%; padding: 0 20px; background-color: #212121; color: white; border-bottom: 1px solid rgba(0, 0, 0, 0.1); z-index: 99; position: relative; @include md { padding: 0 40px; } .header-content { display: flex; justify-content: space-between; align-items: center; height: 50px; max-width: 1200px; margin: 0 auto; @include md { height: 80px; } .hamburger-btn { background: transparent; border: none; color: white; font-size: 20px; cursor: pointer; display: flex; align-items: center; justify-content: center; @include md { display: none; } } .left { list-style-type: none; display: none; gap: 25px; @include md { display: flex; } li { font-size: 14px; font-weight: 600; text-transform: uppercase; cursor: pointer; } } .center { font-size: 22px; font-weight: 700; cursor: pointer; @include md { font-size: 28px; } } .right { display: flex; align-items: center; gap: 20px; font-size: 20px; .cart-icon { position: relative; cursor: pointer; span { position: absolute; top: -8px; right: -8px; background-color: #ff4757; border-radius: 50%; width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700; } } } } .mobile-menu { position: absolute; top: 100%; left: 0; width: 100%; background-color: #212121; border-top: 1px solid rgba(255,255,255,0.1); max-height: 0; overflow: hidden; transition: max-height 0.3s ease; &.open { max-height: 300px; } ul { list-style: none; padding: 15px 20px; display: flex; flex-direction: column; gap: 15px; li { font-size: 16px; font-weight: 600; text-transform: uppercase; cursor: pointer; padding: 10px 0; border-bottom: 1px solid rgba(255,255,255,0.05); &:last-child { border-bottom: none; } } } @include md { display: none; } } } .sticky-header { position: fixed; top: 0; left: 0; box-shadow: 0 2px 10px rgba(0,0,0,0.2); }
关键修改说明
- 状态管理:新增
isMobileMenuOpen状态控制汉堡菜单的显示/隐藏 - 图标引入:使用
react-icons的FaBars和FaTimes实现汉堡/切换图标 - 结构调整:添加汉堡按钮,单独分离移动端菜单结构
- 交互优化:点击菜单链接后自动关闭汉堡菜单,提升用户体验
- 样式完善:
- 汉堡按钮仅在移动端显示
- 移动端菜单使用
max-height配合过渡动画实现平滑展开/收起 - 菜单项样式与桌面端保持风格统一
- 监听清理:在
useEffect中添加事件监听的清理函数,避免内存泄漏
内容的提问来源于stack exchange,提问作者Aditya
相关产品推荐
相关产品推荐

