我正在创建一个多级菜单,并成功创建了一个切换开关,该切换开关可以在单击时打开子菜单。但是,我遇到的问题是单击,所有子菜单都打开了。到目前为止,这是我的代码:
功能
const [isSubOpen, setIsSubOpen] = useState(false)
const toggleSubMenu = (index, e) => {
e.preventDefault()
console.log(index.key)
let test = e.currentTarget.nextElementSibling.id
console.log(test)
if (test == index.key) {
setIsSubOpen(!isSubOpen)
}
}
菜单
<ul>
<li>
<a href={item.url}
onClick={toggleSubMenu.bind(this, { key })}
>
</a>
</li>
</ul>
子菜单
<div id={key} css={isSubOpen ? tw`block` : tw`hidden`}></div>
对它们全部使用单个布尔值将导致它们在状态改变时全部打开和关闭。如果要使所有状态保持一种状态,则可以使用数组或对象来管理每个子菜单。数组是最简单的,所以我将显示一个示例,说明如何工作。
您的状态将是一个由布尔值组成的数组。每个索引代表一个子菜单,false
将关闭,true
将打开。因此,如果单击以打开索引0的第一个子菜单,则将数组设置为[true, false]
。
// Initialize the state with `false` for each sub-menu
const [subMenuState, setSubMenuState] = useState([false, false])
const toggleSubMenu = (e, i) => {
e.preventDefault()
// Clone the array
const newState = subMenuState.slice(0)
// Toggle the state of the clicked sub-menu
newState[i] = !newState[i]
// Set the new state
setSubMenuState(newState)
}
无论何时调用toggleSubMenu
,都将像这样将索引作为第二个参数传递:
<ul>
<li>
<a href="#" onClick={e => toggleSubMenu(e, 0)}>
Link 1
</a>
</li>
<li>
<a href="#" onClick={e => toggleSubMenu(e, 1)}>
Link 2
</a>
</li>
</ul>
然后在子菜单中引用该索引以查看其是否打开:
<div css={subMenuState[0] ? tw`block` : tw`hidden`}>Sub-menu 1</div>
<div css={subMenuState[1] ? tw`block` : tw`hidden`}>Sub-menu 2</div>
我不确定这里的用例,但是对于大多数菜单,您想关闭其他活动子菜单。例如,如果打开了子菜单1,然后单击以打开子菜单2,则希望关闭子菜单1,并打开子菜单2。这是达到此效果的方法:
const [subMenuState, setSubMenuState] = useState([false, false])
const toggleSubMenu = (e, i) => {
e.preventDefault()
// Clone the array
const clone = subMenuState.slice(0)
// Reset all sub-menus except for the one that clicked
const newState = clone.map((val, index) => {
if(index === i) {
return val
}
return false
})
newState[i] = !newState[i]
setSubMenuState(newState)
}
让我知道您是否有任何疑问。希望这对您有所帮助!