React Menu 组件实现方法
基础实现(使用原生 HTML 和 CSS)
import React, { useState } from 'react';
import './Menu.css';
const Menu = () => {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="menu-container">
<button onClick={() => setIsOpen(!isOpen)}>Toggle Menu</button>
{isOpen && (
<ul className="menu-list">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
)}
</div>
);
};
export default Menu;
/* Menu.css */
.menu-container {
position: relative;
}
.menu-list {
list-style: none;
padding: 0;
margin: 0;
border: 1px solid #ddd;
border-radius: 4px;
background: white;
position: absolute;
top: 100%;
left: 0;
width: 200px;
}
.menu-list li {
padding: 8px 12px;
cursor: pointer;
}
.menu-list li:hover {
background: #f0f0f0;
}
使用 Material-UI 实现
import React from 'react';
import { Menu, MenuItem, Button } from '@mui/material';
const MaterialMenu = () => {
const [anchorEl, setAnchorEl] = React.useState(null);
const open = Boolean(anchorEl);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<Button onClick={handleClick}>Open Menu</Button>
<Menu
anchorEl={anchorEl}
open={open}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Item 1</MenuItem>
<MenuItem onClick={handleClose}>Item 2</MenuItem>
<MenuItem onClick={handleClose}>Item 3</MenuItem>
</Menu>
</div>
);
};
export default MaterialMenu;
使用 Ant Design 实现
import React from 'react';
import { Menu, Dropdown, Button } from 'antd';
const AntMenu = () => {
const menu = (
<Menu>
<Menu.Item key="1">Item 1</Menu.Item>
<Menu.Item key="2">Item 2</Menu.Item>
<Menu.Item key="3">Item 3</Menu.Item>
</Menu>
);
return (
<Dropdown overlay={menu}>
<Button>Open Menu</Button>
</Dropdown>
);
};
export default AntMenu;
可复用自定义 Menu 组件
import React, { useState } from 'react';
import PropTypes from 'prop-types';
const CustomMenu = ({ items }) => {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="custom-menu">
<button onClick={() => setIsOpen(!isOpen)}>Toggle Menu</button>
{isOpen && (
<ul className="menu-items">
{items.map((item, index) => (
<li key={index} onClick={item.onClick}>
{item.label}
</li>
))}
</ul>
)}
</div>
);
};
CustomMenu.propTypes = {
items: PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.string.isRequired,
onClick: PropTypes.func,
})
).isRequired,
};
export default CustomMenu;
响应式菜单实现
import React, { useState, useEffect } from 'react';
const ResponsiveMenu = () => {
const [isOpen, setIsOpen] = useState(false);
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth < 768);
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return (
<div>
{isMobile ? (
<button onClick={() => setIsOpen(!isOpen)}>Menu</button>
) : (
<ul className="desktop-menu">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
)}
{isMobile && isOpen && (
<ul className="mobile-menu">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
)}
</div>
);
};
export default ResponsiveMenu;
动画效果增强
import React, { useState } from 'react';
import { CSSTransition } from 'react-transition-group';
import './AnimatedMenu.css';
const AnimatedMenu = () => {
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<button onClick={() => setIsOpen(!isOpen)}>Toggle Menu</button>
<CSSTransition
in={isOpen}
timeout={300}
classNames="menu"
unmountOnExit
>
<ul className="menu">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</CSSTransition>
</div>
);
};
export default AnimatedMenu;
/* AnimatedMenu.css */
.menu-enter {
opacity: 0;
transform: translateY(-10px);
}
.menu-enter-active {
opacity: 1;
transform: translateY(0);
transition: opacity 300ms, transform 300ms;
}
.menu-exit {
opacity: 1;
}
.menu-exit-active {
opacity: 0;
transform: translateY(-10px);
transition: opacity 300ms, transform 300ms;
}

