react typescript实现菜单
使用 React 和 TypeScript 实现菜单
定义菜单项类型
使用 TypeScript 定义菜单项的数据结构,确保类型安全。
interface MenuItem {
id: string;
label: string;
path?: string;
children?: MenuItem[];
}
创建菜单组件
构建一个可复用的菜单组件,支持嵌套子菜单。
import React, { useState } from 'react';
interface MenuProps {
items: MenuItem[];
}
const Menu: React.FC<MenuProps> = ({ items }) => {
const [activeSubMenu, setActiveSubMenu] = useState<string | null>(null);
const handleClick = (id: string) => {
setActiveSubMenu(activeSubMenu === id ? null : id);
};
return (
<ul className="menu">
{items.map((item) => (
<li key={item.id} className="menu-item">
<div
className="menu-label"
onClick={() => item.children && handleClick(item.id)}
>
{item.path ? <a href={item.path}>{item.label}</a> : item.label}
{item.children && <span className="arrow">▼</span>}
</div>
{item.children && activeSubMenu === item.id && (
<Menu items={item.children} />
)}
</li>
))}
</ul>
);
};
添加基本样式
为菜单添加简单的 CSS 样式,使其更美观。
.menu {
list-style: none;
padding: 0;
}
.menu-item {
margin: 5px 0;
}
.menu-label {
display: flex;
justify-content: space-between;
padding: 8px;
background: #f0f0f0;
cursor: pointer;
}
.menu-label a {
text-decoration: none;
color: #333;
}
.arrow {
margin-left: 10px;
}
使用菜单组件
在父组件中使用菜单组件,并传递菜单数据。
const App: React.FC = () => {
const menuItems: MenuItem[] = [
{
id: '1',
label: 'Home',
path: '/home',
},
{
id: '2',
label: 'Products',
children: [
{
id: '2-1',
label: 'Laptops',
path: '/products/laptops',
},
{
id: '2-2',
label: 'Phones',
path: '/products/phones',
},
],
},
{
id: '3',
label: 'Contact',
path: '/contact',
},
];
return (
<div className="app">
<Menu items={menuItems} />
</div>
);
};
扩展功能
添加更多功能,如高亮当前选中菜单项或支持图标。
interface MenuItem {
id: string;
label: string;
path?: string;
icon?: React.ReactNode;
children?: MenuItem[];
}
const Menu: React.FC<MenuProps> = ({ items }) => {
const [activeSubMenu, setActiveSubMenu] = useState<string | null>(null);
const [activeItem, setActiveItem] = useState<string | null>(null);
const handleClick = (id: string) => {
setActiveSubMenu(activeSubMenu === id ? null : id);
};
const handleSelect = (id: string) => {
setActiveItem(id);
};
return (
<ul className="menu">
{items.map((item) => (
<li
key={item.id}
className={`menu-item ${activeItem === item.id ? 'active' : ''}`}
>
<div
className="menu-label"
onClick={() => {
if (item.children) {
handleClick(item.id);
} else {
handleSelect(item.id);
}
}}
>
{item.icon && <span className="menu-icon">{item.icon}</span>}
{item.path ? (
<a href={item.path}>{item.label}</a>
) : (
<span>{item.label}</span>
)}
{item.children && <span className="arrow">▼</span>}
</div>
{item.children && activeSubMenu === item.id && (
<Menu items={item.children} />
)}
</li>
))}
</ul>
);
};
响应式设计
使用媒体查询使菜单在不同屏幕尺寸下表现良好。
@media (max-width: 768px) {
.menu {
width: 100%;
}
.menu-item {
width: 100%;
}
}
通过以上步骤,可以构建一个功能完善、类型安全的 React TypeScript 菜单组件。根据实际需求,可以进一步扩展功能或调整样式。







