菜单项随url的变化自动切换
基于上一节内容,可以实现点击menu组件中的菜单项,然后跳转到对应的页面,但如果直接在浏览器中通过url访问,就会自动跳转到首页。
这是因为我们在函数组件中初始化了current的值为home。
同时,我们将为新增一个侧边栏做准备。
基于上述两点:
- 需要首先将子组件内的交互逻辑转移到父组件中,来更好的进行状态管理。
- 其次,将点击MenuItem的逻辑 和跳转的逻辑分开。
新的内容:useLocation
参看 :https://reactrouter.com/en/6.8.0/hooks/use-location
该hooks返回当前的location对象,通过location.pathname可以得知当前url
// MainLayout.jsx
import { Outlet } from 'react-router-dom'
import { Layout } from 'antd'
import { AppstoreOutlined, MailOutlined, SettingOutlined } from '@ant-design/icons'
import { useNavigate,useLocation } from "react-router-dom"
import { useState, useEffect } from 'react'
import HeadBar from '../../components/HeadBar'
import SideBar from '../../components/SideBar'
import { headerStyle, contentStyle, siderStyle, footerStyle } from './layoutStyles.js'
const { Header, Footer, Sider, Content } = Layout
const menuList = [
{
label: 'home',
key: 'home',
icon: <MailOutlined />,
sideList: []
},
{
label: 'about',
key: 'about',
icon: <AppstoreOutlined />,
sideList: [
{
key: 'aboutMe',
icon: <AppstoreOutlined />,
label: 'aboutMe'
},
{
key: 'myReading',
icon: <MailOutlined />,
children: [
{
key: 'englishBooks',
icon: <AppstoreOutlined />,
label: 'englishBooks'
},
{
key: 'chineseBooks',
icon: <SettingOutlined />,
label: 'chineseBooks'
},
],
label: 'myReading'
}
]
}
]
function MainLayout() {
/**
* 整个页面的逻辑分两块:
* 当通过url访问页面时,menu的默认选中根据url走
* 当点击menu item 的时候,根据点击的item 跳转页面。
*/
const navigate = useNavigate()
const location = useLocation()
const [headBarCurrent,changeHeadBarCurrent] = useState('')
const [clickChange,changeClickChange] = useState(null)
useEffect(()=>{ // 当location发生变化时 需要更改菜单选中值
const path = location.pathname
menuList.map(e=>{
const key = e.key
if(path.indexOf(key) !== -1){
changeHeadBarCurrent(key)
}
})
},[location])
useEffect(()=>{ // 在菜单点击事件发生时
if(clickChange){ // 跳转页面
navigate(clickChange)
}
},[clickChange])
const onHeadBarClick = (e) => { // 当顶部导航栏触发点击的时候 需要更新两个值
changeHeadBarCurrent(e.key) // 告知菜单选中值发生了变化
const url = '/' + e.key
changeClickChange(url) // 告知触发了菜单点击事件 需要跳转页面了
}
return (
<div>
<Layout>
<Header style={headerStyle}><HeadBar menuList={menuList} current={headBarCurrent} onClick={onHeadBarClick} /></Header>
<Layout>
<Layout>
<Content style={contentStyle}>
<Outlet />
</Content>
<Footer style={footerStyle}>footer</Footer>
</Layout>
</Layout>
</Layout>
</div>
)
}
export default MainLayout
// HeadBar.jsx
import { Menu } from 'antd'
function HeadBar(props) {
return (
<Menu onClick={props.onClick} selectedKeys={props.current} mode="horizontal" items={props.menuList} />
)
}
export default HeadBar
项目各依赖的版本:
“antd”: “^5.1.7”,
“react”: “^18.2.0”,
“react-dom”: “^18.2.0”,
“react-router-dom”: “^6.8.0”,