html - 带有反应的导航菜单
问题描述
我有一个导航菜单,我想在单击的列表项上运行一个功能,以打开一个子菜单。现在发生的事情是我单击一个项目并显示所有子菜单。我在为每个子菜单使用单独的值之前使其工作,我想知道是否可以使用单个函数而不是复制和粘贴相同的函数 2更多次。有什么建议吗?这是我的代码
import React, { useEffect } from "react";
import { useImmer } from "use-immer";
// Submenu component
import Submenu from "./Submenu";
function Navbar() {
const [state, setState] = useImmer({
menu: false
});
/*
return function menu(sub) {
setState(draft => {
draft.sub = !draft.sub;
});
};
*/
function handleSubMenu(e) {
e.preventDefault();
setState(draft => {
draft.menu = !draft.menu;
});
}
return (
<>
<li className="navbar-main__item navbar-main__item--1">
<a onClick={handleSubMenu} href="#" className=" navbar-main__link">
<span>List item 1</span>{" "}
<svg
className={
state.menu
? "navbar-main__icon navbar-main__icon--rotate-down"
: "navbar-main__icon navbar-main__icon--rotate"
}
>
<use href="img/sprite.svg#icon-chevron-thin-down" />
</svg>
</a>
<Submenu
subfirst="Item 1"
subsecond="Item 2"
subthird="Meat 3"
state={state.menu}
/>
</li>
<li className="navbar-main__item navbar-main__item--2">
<a onClick={handleSubMenu} data-id="1" href="#" className="navbar-main__link">
<span>List Item 2</span>{" "}
<svg
className={
state.menu
? "navbar-main__icon navbar-main__icon--rotate-down"
: "navbar-main__icon navbar-main__icon--rotate"
}
>
<use href="img/sprite.svg#icon-chevron-thin-down" />
</svg>
</a>
<Submenu
subfirst="Item 1"
subsecond="Item 2"
subthird="Item 3"
state={state.menu}
/>
</li>
<li className="navbar-main__item navbar-main__item--3">
<a onClick={handleSubMenu} href="#" className="navbar-main__link">
<span>List Item 3</span>{" "}
<svg
className={
state.menu
? "navbar-main__icon navbar-main__icon--rotate-down"
: "navbar-main__icon navbar-main__icon--rotate"
}
>
<use href="img/sprite.svg#icon-chevron-thin-down" />
</svg>
</a>
<Submenu
subfirst="Item 1"
subsecond="Item 2"
subthird="Item 3"
state={state.menu}
/>
</li>
</>
);
}
export default Navbar;
解决方案
为了对每个函数重用相同的函数,您必须修改您在状态中存储的内容。menu
是一个布尔值,所以它只能有两个值之一。但是,如果您为每个子菜单存储一个唯一标识符,则可以根据该标识符更改子菜单是否打开。例如,如果每个子菜单都有一个 id,并且您将该 id 存储在 state 中,您可以将该 id 与子菜单的 id 进行比较,并传递 true/false 以判断它是否打开。
您可以对该组件进行一些其他改进,以减少重复性。有很多重复可以简化。
import React from "react";
import { useImmer } from "use-immer";
import Submenu from "./Submenu";
const menuItems = [
{
id: 'menu1',
subfirst: "Item 1",
subsecond: "Item 2",
subthird: "Meat 3",
},
{
id: 'menu2',
subfirst: "Item 1",
subsecond: "Item 2",
subthird: "Item 3",
},
{
id: 'menu3',
subfirst: "Item 1",
subsecond: "Item 2",
subthird: "Item 3",
},
];
function Navbar() {
const [state, setState] = useImmer({ openMenuId: undefined });
function openSubMenu(menuId) {
e.preventDefault();
setState(draft => {
draft.openMenuId = menuId;
});
}
return (
<ul style={{ listStyle: 'none' }}>
{menuItems.map((menuItem, index) => (
<li className={`navbar-main__item navbar-main__item--${index}`}>
<a onClick={() => openSubMenu(menuItem.id)} href="#" className="navbar-main__link">
<span>List item {index}</span>
<svg
className={`navbar-main__icon navbar-main__icon--rotate${state.openMenuId === menuItem.id ? '-down' : ''}`}
>
<use href="img/sprite.svg#icon-chevron-thin-down" />
</svg>
</a>
<Submenu
subfirst={menuItem.subfirst}
subsecond={menuItem.subsecond}
subthird={menuItem.subthird}
isOpen={state.openMenuId === menuItem.id}
/>
</li>
))}
</ul>
);
}
export default Navbar;
不过,这只是一个快速的传递。对于这种情况, useImmer 可能是矫枉过正,除非您打算向状态添加更多内容。
推荐阅读
- postgresql - 是否可以防止删除但不能使用外键插入?
- java - 如何在 Selenium 中定位 ::before 元素并获取其内容?
- javascript - 为什么忽略库上设置的“developmentMode”标志?
- ios - 快速重载赋值运算符
- powershell - 从 PowerShell 发送电子邮件
- javascript - 彩票Javascript
- python - 将输出转换为 pandas 数据框
- c# - 使用日期和月份计算 CalenderWeek
- node.js - 新的 package.json `exports` 字段不适用于 TypeScript
- google-apps-script - 如果单元格“y”大于单元格“x”,则自动将单元格“y”复制到单元格“x”