export const asyncRouterMap = [
{
path: '/page1',
title: 'page1',
icon: 'HomeOutlined',
}, {
path: '/page2',
title: 'page2',
icon: 'HomeOutlined',
}, {
path: '/page3',
title: 'page3',
icon: 'HomeOutlined',
children: [
{
path: '/page301',
title: 'page301',
icon: 'HomeOutlined',
}, {
path: '/page302',
title: 'page302',
icon: 'HomeOutlined',
}, {
path: '/page303',
title: 'page303',
icon: 'HomeOutlined',
}
]
},{
path: '/page4',
title: 'page4',
icon: 'HomeOutlined',
children: [
{
path: '/page401',
title: 'page401',
icon: 'HomeOutlined',
}, {
path: '/page402',
title: 'page402',
icon: 'HomeOutlined',
}
]
}
]
使用path當(dāng)作Menu的key.
1.菜單欄展開和回收事件
點(diǎn)擊菜單,收起其他展開的所有菜單,只留下一個(gè)。
Menu的onOpenChange
方法:SubMenu 展開/ 關(guān)閉的回調(diào)函數(shù),展開和回收某項(xiàng)菜單時(shí)的事件。
Menu的openKeys
屬性:當(dāng)前展開的SubMenu菜單項(xiàng)的key數(shù)組,當(dāng)前菜單展開項(xiàng)的key數(shù)組。
當(dāng)前要展開哪一項(xiàng)的openKeys將來(lái)是要變化的,需要存到state中。
state={
openKey:['']
}
//展開和回收某項(xiàng)菜單,把openKeys的數(shù)組值變?yōu)閗eys數(shù)組的最后一項(xiàng),只要一項(xiàng)是展開的,就是我剛點(diǎn)擊的這一項(xiàng)
handleOpenChange=(keys)=>{
//keys是一個(gè)字符串?dāng)?shù)組,記錄了當(dāng)前哪一項(xiàng)是展開的(用key來(lái)記錄)
//console.log(keys)
/* 點(diǎn)擊page3 keys輸出["",'/page3'],再點(diǎn)擊page4 keys輸出["",'/page4'],點(diǎn)擊誰(shuí)keys數(shù)組的最后一項(xiàng)就是誰(shuí)*/
this.setState({
openKeys:[keys[keys.length-1]]
})
}
<Menu
defaultSelectedKeys={['/home']}
mode="inline"
theme="dark"
style={{ height: "100vh" }}
openKeys={openKeys}
onOpenChange={this.handleOpenChange}
>
2. 刷新時(shí)默認(rèn)當(dāng)前選中項(xiàng)樣式的處理
根據(jù)用戶的操作習(xí)慣,選中一個(gè)二級(jí)菜單節(jié)點(diǎn)的時(shí)候,刷新頁(yè)面的時(shí)候應(yīng)該保持用戶之前的選中狀態(tài),并且二級(jí)菜單展開項(xiàng)應(yīng)該默認(rèn)展開。
2.1 刷新頁(yè)面菜單保持用戶之前的選中狀態(tài)
現(xiàn)在的情況是點(diǎn)擊page2頁(yè)面,組件在page2頁(yè)面,在這時(shí)刷新頁(yè)面,導(dǎo)航欄的高亮選中變成了第一項(xiàng),但是組件還是page2頁(yè)面,出現(xiàn)了選中菜單與頁(yè)面不符合的情況,我們希望的是點(diǎn)擊了刷新頁(yè)面之后組件在page2頁(yè)面并且導(dǎo)航欄選中項(xiàng)也是這個(gè)。
Menu的selectedKeys
屬性:表示當(dāng)前樣式所在的選中項(xiàng)key,不能直接寫死,通過(guò)獲取當(dāng)前的路徑拿到key。
怎么獲取當(dāng)前路徑呢?對(duì)于類組件,使用this.props.location.pathname
拿到的就是當(dāng)前頁(yè)面的路徑;對(duì)于函數(shù)式組件,使用hooks的useLocation().pathname
拿到當(dāng)前頁(yè)面的路徑。
獲取到當(dāng)前頁(yè)面的路徑后作為值修改selectedKeys的值。
state={
openKey:[''],
selectedKey:['']
}
/* this.changeSelectKeys()這個(gè)函數(shù)要在要在componentDidMount中調(diào)用一次,
再在componentUpdate中再調(diào)用。
這是因?yàn)閏omponentDidMount只在第一次render之后執(zhí)行一次,
后續(xù)的rendr執(zhí)行后會(huì)執(zhí)行componentDidUpdate;
從登錄頁(yè)進(jìn)入到首頁(yè)后會(huì)先mount,然后有setState,會(huì)發(fā)生update,
點(diǎn)擊切換菜單欄只會(huì)再執(zhí)行componentUpdate,
不會(huì)再執(zhí)行componentDidMount了。*/
/*在componentDidUpdate生命周期方法中加入
判斷當(dāng)前頁(yè)面路徑是否與上一個(gè)頁(yè)面路徑相同
是為了避免不必要的狀態(tài)更新和重新渲染,從而防止死循環(huán)的發(fā)生。
如果沒(méi)有這個(gè)判斷,每次組件更新時(shí)都會(huì)執(zhí)行changeSelectedKey方法,
該方法會(huì)根據(jù)當(dāng)前路徑更新菜單狀態(tài)。
然而,更新狀態(tài)又會(huì)導(dǎo)致組件重新渲染,這將再次觸發(fā)componentDidUpdate方法,形成一個(gè)無(wú)限循環(huán)。
通過(guò)添加判斷,我們可以確保只有在當(dāng)前頁(yè)面路徑與上一個(gè)頁(yè)面路徑不同時(shí)才會(huì)更新菜單狀態(tài),
從而避免了不必要的循環(huán)更新。*/
componentDidUpdate(prevProps) {
// 這里必須要有這個(gè)前后路徑是否一致的判斷,否則會(huì)出現(xiàn)死循環(huán)
if (prevProps.location.pathname !== this.props.location.pathname) {
this.changeSelected();
}
}
componentDidMount() {
this.changeSelected();
}
changeSelected = () => {
//根據(jù)當(dāng)前頁(yè)面路由修改當(dāng)前選中的菜單項(xiàng)key數(shù)組
//獲取當(dāng)前頁(yè)面路徑(切割后的key) 由于我們?cè)O(shè)計(jì)的當(dāng)前頁(yè)面路徑與key不完全一致需要做切割
const currentRoute = this.props.location.pathname.split('/index')[1]
this.setState({
selectedKey: [currentRoute]
})
}
<Menu
defaultSelectedKeys={['/home']}
selectedKeys={selectedKey}
mode="inline"
theme="dark"
style={{ height: "100vh" }}
openKeys={openKeys}
onOpenChange={this.handleOpenChange}
>
現(xiàn)在能夠?qū)崿F(xiàn)的是頁(yè)面刷新保持用戶的選中狀態(tài),但是當(dāng)我們點(diǎn)擊的是page301再刷新頁(yè)面時(shí),雖然該菜單項(xiàng)會(huì)被選中,但是菜單欄中page301沒(méi)有被展開,需要再進(jìn)行下面的配置。
2.2 配置展開項(xiàng)openKeys的初始值
需要修改openKeys數(shù)組,openKeys的展開項(xiàng)是不能寫死的,刷新頁(yè)面后誰(shuí)展開是跟路徑有關(guān)的。
整體思路是:拿著this.props.location.pathname與items數(shù)組的每一項(xiàng)的children的key值進(jìn)行對(duì)比,如果找到了相等了,就要他上一級(jí)的key給到openKeys數(shù)組的元素,作為初始值。
(這個(gè)思路更加通用一些)
整體思路:根據(jù)this.props.location.pathname拿到它上一級(jí)的key,比如’/page3/page301’要想辦法拿到‘/page3’,’/page3/page301/page30101’要想辦法拿到’/page3/page301’,把openKeys的值改為拿到的它上一級(jí)的key,這個(gè)操作可以跟隨changeSelectedKey操作放在一個(gè)函數(shù)中。(這種方法比較簡(jiǎn)單,但是要求key的格式必須是 /page3/page301 這樣的)
changeSelected = () => {
//根據(jù)當(dāng)前頁(yè)面路由修改當(dāng)前選中的菜單項(xiàng)key數(shù)組
//獲取當(dāng)前頁(yè)面路徑(切割后的key) 由于我們?cè)O(shè)計(jì)的當(dāng)前頁(yè)面路徑與key不完全一致需要做切割
const currentRoute = this.getCurrentRoute()
// pathname: /home /student/exam /student/exam/a
// 想要的結(jié)果 /home /student /student/exam
//先拆開在拼起來(lái)
//拆開 ['',home] ['','student','exam'] ['','student','exam','a']
//取1~倒數(shù)第二項(xiàng) ['student'] ['student','exam']
//拼接起來(lái)
let openKeys=[]
if(currentRoute.split('/').length>2){
openKeys=[`/${currentRoute.split('/').slice(1, -1).join('/')}`]
}
// console.log(openKeys)
this.setState({
selectedKey: [currentRoute],
openKeys
})
}
componentDidMount用于刷新頁(yè)面時(shí)頁(yè)面卸載又重新掛載,componentDidUpdate用于不刷新頁(yè)面只點(diǎn)擊菜單欄。
在使用React類組件時(shí),調(diào)用updateMenuState
方法既在componentDidMount
中也在componentDidUpdate
中是為了確保無(wú)論組件是在初次掛載還是在更新后,都能根據(jù)當(dāng)前的路由路徑正確設(shè)置菜單的選中狀態(tài)和展開狀態(tài)。
這兩個(gè)生命周期方法各自承擔(dān)著不同的職責(zé):
-
componentDidMount
:這個(gè)方法在組件首次渲染到DOM中后被調(diào)用。此時(shí),你可以進(jìn)行API調(diào)用、設(shè)置狀態(tài)等操作。對(duì)于導(dǎo)航菜單來(lái)說(shuō),當(dāng)組件首次加載時(shí),你需要根據(jù)當(dāng)前的路由路徑初始化菜單的狀態(tài),包括哪個(gè)菜單項(xiàng)被選中以及哪些子菜單應(yīng)該展開。因?yàn)樵趹?yīng)用首次加載時(shí),用戶可能直接通過(guò)URL訪問(wèn)特定頁(yè)面,所以需要在這個(gè)時(shí)刻根據(jù)URL設(shè)置正確的菜單狀態(tài)。 -
componentDidUpdate
:這個(gè)方法在組件更新后被調(diào)用。在React中,組件的更新可能由props或state的改變引起,也可能是由于父組件的重新渲染觸發(fā)。在導(dǎo)航菜單的情況下,用戶可能通過(guò)點(diǎn)擊鏈接或其他方式導(dǎo)致路由的變化,因此需要在組件更新后再次檢查當(dāng)前的路由路徑,以確保菜單狀態(tài)與當(dāng)前頁(yè)面匹配。因此,在componentDidUpdate
中調(diào)用updateMenuState
方法,可以在組件更新后根據(jù)新的路由路徑更新菜單狀態(tài),保持菜單的正確顯示。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-850316.html
參考內(nèi)容:React 中使用antd,刷新時(shí)被選中的menu二級(jí)菜單初始化的展開問(wèn)題
??????????????????React+Ant Design 4.4.1實(shí)現(xiàn)左側(cè)二級(jí)導(dǎo)航(可配置路由、所有路由層級(jí)可統(tǒng)一、可根據(jù)路由高亮菜單項(xiàng)、刷新時(shí)可自動(dòng)展開定位到當(dāng)前路由)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-850316.html
到了這里,關(guān)于react17+antd4 Menu 點(diǎn)擊菜單收起其他展開的所有菜單、頁(yè)面刷新時(shí)設(shè)置菜單的選中狀態(tài)和展開狀態(tài)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!