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

React项目中如何实现点击显示、移开隐藏的下拉菜单?

解决React下拉菜单显示/隐藏问题

核心问题分析

你的代码缺少状态管理来控制下拉菜单的显示与隐藏,且直接操作DOM的方式不符合React组件化思维。我们需要通过React的useState钩子管理菜单状态,并通过事件处理器实现交互逻辑。

修复步骤

1. 更新Navigation.jsx,添加状态管理与交互逻辑

  • 引入useState钩子
  • 添加控制下拉菜单可见性的状态
  • 为Services选项添加点击事件切换菜单状态
  • 传递状态和隐藏回调给MenuDropdown组件
  • 为其他导航项添加点击隐藏菜单的逻辑

修改后的Navigation.jsx代码:

import logo from './favicon.png'
import { motion } from "framer-motion"
import { useInView } from "react-intersection-observer"
import MenuDropdown from "./MenuDropdown"
import { Link } from 'react-router-dom'
import { useState } from 'react'

export default function Navigation() {

   const [ref, inView] = useInView({ triggerOnce: false })
   const [isDropdownVisible, setIsDropdownVisible] = useState(false)

   const hideDropdown = () => setIsDropdownVisible(false)

   return (
    <motion.nav className="flex items-center justify-between flex-wrap px-6 lg:px-12 py-8 max-w-full mx-auto" ref={ref} initial={{ y: -10, opacity: 0 }} animate={inView? { y: 0, opacity: 1 }: {}} exit={{ y: -10, opacity: 0 }} transition={{ duration: 0.5 }}>
        <a href="/" className="flex flex-row items-center flex-shrink-0 text-white mr-6 lg:pr-16 space-x-2">
          <img src={logo} className='w-8 h-8' alt='Logo'></img>
          <h2 className="font-bold text-2xl tracking-tight">Sample </h2>
        </a>
        
        <div id='menu' className="block lg:hidden">
          <button className="flex items-center px-3 py-2 border rounded text-slate-200 border-slate-400 duration-100 hover:text-white hover:border-white">
            <svg className="fill-current h-3 w-3" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><title>Menu</title><path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"/></svg>
          </button>
        </div>

        <div className="lg:flex flex-none w-6/12 hidden">
          <div className="lg:flex-grow flex flex-rows space-x-12 text-sm">
            <div className="flex flex-rows items-center space-x-2 text-white" onClick={hideDropdown}>
              <span className="ring-1 p-0.5 ring-white rounded-full"></span>
              <Link to="projects" className="block mt-4 lg:inline-block lg:mt-0 text-white mr-4">
                Home
              </Link>
            </div>

            <div id="mega-menu" className="flex flex-rows items-center space-x-2 text-white">
              <span className="ring-1 p-0.5 ring-white rounded-full"></span>
              <div className="block mt-4 lg:inline-block lg:mt-0 mr-4 cursor-pointer" onClick={() => setIsDropdownVisible(!isDropdownVisible)}>
                Services
              </div>
              <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1} stroke="currentColor" className="w-4 h-4">
                <path strokeLinecap="round" strokeLinejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
              </svg>
            </div>
            <div className="flex flex-rows items-center space-x-2 text-white" onClick={hideDropdown}>
              <span className="ring-1 p-0.5 ring-white rounded-full"></span>
              <a href="about" className="block mt-4 lg:inline-block lg:mt-0 text-white mr-4">
                About
              </a>
            </div>
            <div className="flex flex-rows items-center space-x-2 text-white" onClick={hideDropdown}>
              <span className="ring-1 p-0.5 ring-white rounded-full"></span>
              <a href="careers" className="block mt-4 lg:inline-block lg:mt-0 text-white mr-4">
                Careers
              </a>
            </div>
            <div className="flex flex-rows items-center space-x-2 text-white" onClick={hideDropdown}>
              <span className="ring-1 p-0.5 ring-white rounded-full"></span>
              <a href="contact" className="block mt-4 lg:inline-block lg:mt-0 text-white mr-4">
                Contact
              </a>
            </div>
          </div>
        </div>

        <MenuDropdown isVisible={isDropdownVisible} onHide={hideDropdown}></MenuDropdown>
        
    </motion.nav>
   )
}

2. 更新MenuDropdown.jsx,接收状态并添加鼠标离开事件

  • 添加props参数接收isVisible和onHide
  • 动态控制hidden类的显示
  • 为菜单容器添加鼠标离开事件触发隐藏

修改后的MenuDropdown.jsx代码:

import { Link } from "react-router-dom"

const MenuDropdown = ({ isVisible, onHide }) =>  {

    return (
        <div className={`absolute top-20 right-0 bg-white shadow-lg text-gray-500 w-full mx-auto p-12 ${isVisible ? '' : 'hidden'}`} onMouseLeave={onHide}>
            <div className="flex flex-row flex-nowrap space-x-6 justify-between">
                <div className="space-y-2 flex-none w-3/12 border-r">
                    <h2 className="text-2xl font-semibold text-slate-900">Services</h2>
                    <p className="text-base">Lorem Ipsum es simplemente el texto de relleno de las imprentas y archivos de texto..</p>
                </div>
                <div className="flex flex-col space-y-4">
                    <h2 className="text-base text-slate-900 font-bold">Option 1</h2>
                    <p className="text-sm">Lorem Ipsum es simplemente el texto de relleno de las imprentas y archivos de texto..</p>
                    <Link to="strategy">
                        <button className="border border-slate-900 flex-none w-6/12 text-black py-2 px-4 rounded-full capitalize text-center hover:bg-slate-900 hover:text-white">
                            <span className="text-xs">Learn More</span>
                        </button>
                    </Link>
                </div>
                <div className="flex flex-col space-y-4">
                    <h2 className="text-base text-slate-900 font-bold">Option 2</h2>
                    <p className="text-sm">Lorem Ipsum es simplemente el texto de relleno de las imprentas y archivos de texto..</p>
                    <Link to="design">
                        <button className="border border-slate-900 flex-none w-6/12 text-black py-2 px-4 rounded-full capitalize text-center hover:bg-slate-900 hover:text-white">
                            <span className="text-xs">Learn More</span>
                        </button>
                    </Link>
                </div>
                <div className="flex flex-col space-y-4">
                    <h2 className="text-base text-slate-900 font-bold">Option 3</h2>
                    <p className="text-sm">Lorem Ipsum es simplemente el texto de relleno de las imprentas y archivos de texto.</p>
                    <Link to="technology">
                        <button className="border border-slate-900 flex-none w-6/12 text-black py-2 px-4 rounded-full capitalize text-center hover:bg-slate-900 hover:text-white">
                            <span className="text-xs">Learn More</span>
                        </button>
                    </Link>
                </div>
            </div>
        </div>
    )
}

export default MenuDropdown

额外优化建议

  • 可添加点击页面其他区域隐藏菜单的逻辑(需监听document的click事件)
  • 为菜单显示/隐藏添加过渡动画(可使用framer-motion或Tailwind的transition类)
  • 避免直接使用document.getElementById,React中优先通过状态和props管理组件交互

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 16:22:16