React實(shí)現(xiàn)路由返回?cái)r截的三種方式
背景
最近項(xiàng)目為了避免用戶誤操作導(dǎo)致數(shù)據(jù)丟失,增加返回?cái)r截功能,但是之前由于qiankun的報(bào)錯(cuò)導(dǎo)致這個(gè)功能一直有一些問題,所以專門獨(dú)立搞了一個(gè)專題研究在react中各種方式實(shí)現(xiàn)這個(gè)功能,組內(nèi)小伙伴使用的是prompt方式,實(shí)現(xiàn)的還是比較方便,我打算探索另外別的方式實(shí)現(xiàn),想用hooks的方式實(shí)現(xiàn)
技術(shù)棧:
- react17
- react-router5
方法一:使用history.block方式實(shí)現(xiàn)
場景:需要靈活定制彈框樣式,需要比對跳轉(zhuǎn)地址和當(dāng)前地址
不足:還需要手動(dòng)放行,并且手動(dòng)實(shí)現(xiàn)跳轉(zhuǎn)
函數(shù)有兩個(gè)參數(shù),第一個(gè)是一個(gè)對象,包含要跳轉(zhuǎn)的地址等信息,第二個(gè)是觸發(fā)的動(dòng)作,包含三個(gè)值POP,REPLACE,PUSH,可以根據(jù)這三個(gè)類型,定制開發(fā)一些業(yè)務(wù)邏輯,函數(shù)的返回值是解除限制函數(shù),比如只想回退攔截,手動(dòng)點(diǎn)擊跳轉(zhuǎn)不攔截,就可以判斷action是POP的時(shí)候返回false
實(shí)現(xiàn)方式如下:
useEffect(() => {
//這里要緩存函數(shù)返回的方法,返回的函數(shù)是解除限制函數(shù),想解除直接調(diào)用一下
unblockRef.current = history.block((tx, action) => {
setTargetPathname(tx.pathname)//緩存目標(biāo)路徑 之所以緩存,是為了彈框點(diǎn)擊確認(rèn)的時(shí)候可以獲取到
const isBlock = history.location.pathname != tx.pathname//當(dāng)跳轉(zhuǎn)的目標(biāo)地址不是當(dāng)前地址,則攔截,只要不在當(dāng)前頁面就攔截
setOpen(isBlock)
return isBlock == true ? false : true ////返回false是阻塞, 返回true是不阻塞 注意這里和block的值正好相反
})
return () => {
unblockRef.current()// 組件卸載之后要解除限制
}
}, [history])
下面定義一個(gè)自定義的彈框,直接用原生dialog元素寫個(gè)
<dialog className="dialog" open={open}>
<p>確認(rèn)離開么<br /></p>
<button onClick={cancel}>取消</button>
<button onClick={handleConfirm}>確定</button>
</dialog>
注意,當(dāng)點(diǎn)擊確認(rèn)的時(shí)候,需要先解除限制,然后再跳轉(zhuǎn)一下之前要跳轉(zhuǎn)的鏈接,官方說有個(gè)retry的方法,我一直沒有找到該方法,也可能我的react-router版本低吧
const handleConfirm = () => {
setOpen(false)
if (unblockRef.current) {
unblockRef.current();//釋放限制
}
history.push(targetPathname)//從新跳轉(zhuǎn)之前要跳轉(zhuǎn)的頁面
}
方法二:使用prompt結(jié)合message函數(shù)實(shí)現(xiàn)自定義彈框
場景: 需要通過開關(guān)控制是否攔截,并需要自定義ui,需要比對跳轉(zhuǎn)地址
不足:當(dāng)點(diǎn)擊通過的時(shí)候,如果不延時(shí)會(huì)存在狀態(tài)更新不及時(shí)導(dǎo)致不能正常跳轉(zhuǎn)
prompt接受一個(gè)when的參數(shù),true代表攔截 message可以是一個(gè)字符串或者是一個(gè)函數(shù),如果是字符串則調(diào)用系統(tǒng)默認(rèn)彈框, 如果想自定義彈框則需要在函數(shù)里控制,函數(shù)返回boolean值,false代表攔截,true代表放
<Prompt when={isBlock} message={(location) => {
if (location.pathname !== history.location.pathname) {
setTargetPathname(location.pathname)
setIsBlock(true)
setOpen(true)
return false//返回false是攔截
} else {
setIsBlock(false)
return true//true是放行
}
}}></Prompt>
當(dāng)想點(diǎn)擊確認(rèn)跳轉(zhuǎn)的時(shí)候,要先解除限制,然后再手動(dòng)跳轉(zhuǎn),由于狀態(tài)可能更新不及時(shí),所以設(shè)置幾百毫秒之后再跳轉(zhuǎn)
const handleConfirm = () => {
setIsBlock(false)
setOpen(false)
//需要等待鎖釋放之后才能跳轉(zhuǎn)
setTimeout(() => {
history.push(targetPathname)//從新跳轉(zhuǎn)之前要跳轉(zhuǎn)的頁面
console.log('確認(rèn)')
}, 100)
}
const cancel = () => {
setOpen(false)
}
方法三:基于prompt,修改路由getUserConfirmation實(shí)現(xiàn)自定義彈框攔截
場景:需要全局統(tǒng)一樣式,彈框樣式固定,需要靈活控制攔截條件
不足:
由于攔截彈框是在全局進(jìn)行攔截,所以如果不同頁面要求不同攔截彈框不太好實(shí)現(xiàn)
不太好判斷要跳轉(zhuǎn)到的地址和當(dāng)前地址比對
頁面中只需要寫如下,通過一個(gè)開關(guān)控制是否攔截,給一個(gè)錯(cuò)誤的提示
<Prompt when={isBlock} message={'自定義---確定你要返回么?。。。?!'}></Prompt>
然后再路由定義的時(shí)候增加如下,增加一個(gè)getUserConfirmation配置,用來獲取prompt傳過來的攔截消息,并緩存callback函數(shù),這個(gè)函數(shù)用來控制是否放行
<Router
getUserConfirmation={(message, callback) => {
callbackRef.current = callback
setMessage(message)
setOpen(true)
}
}
>
當(dāng)點(diǎn)擊確認(rèn)跳轉(zhuǎn)則調(diào)用callback(true),點(diǎn)擊取消則調(diào)用callback(false),路徑地址就變回來了, callback(true)不需要再手動(dòng)跳轉(zhuǎn),會(huì)自動(dòng)跳轉(zhuǎn)
const handleConfirm = () => {
setOpen(false)
callbackRef.current?.(true)
}
const cancel = () => {
callbackRef.current?.(false)
setOpen(false)
}
到此這篇關(guān)于React實(shí)現(xiàn)路由返回?cái)r截的三種方式的文章就介紹到這了,更多相關(guān)React路由返回?cái)r截內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
ReactiveCocoa代碼實(shí)踐之-UI組件的RAC信號(hào)操作
這篇文章主要介紹了ReactiveCocoa代碼實(shí)踐之-UI組件的RAC信號(hào)操作 的相關(guān)資料,需要的朋友可以參考下2016-04-04
react native帶索引的城市列表組件的實(shí)例代碼
本篇文章主要介紹了react-native城市列表組件的實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08
React?Native實(shí)際項(xiàng)目中的經(jīng)驗(yàn)和踩坑記錄
在當(dāng)今移動(dòng)應(yīng)用開發(fā)的浪潮中,React Native以其跨平臺(tái)、高效開發(fā)的特點(diǎn)脫穎而出,成為眾多開發(fā)者首選的框架之一,這篇文章主要介紹了React Native實(shí)際項(xiàng)目中的經(jīng)驗(yàn)和踩坑記錄的相關(guān)資料,需要的朋友可以參考下2026-03-03
react-native-tab-navigator組件的基本使用示例代碼
本篇文章主要介紹了react-native-tab-navigator組件的基本使用示例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下2017-09-09
Remix后臺(tái)開發(fā)之remix-antd-admin配置過程
這篇文章主要為大家介紹了Remix后臺(tái)開發(fā)之remix-antd-admin配置過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
react實(shí)現(xiàn)阻止父容器滾動(dòng)
這篇文章主要介紹了react實(shí)現(xiàn)阻止父容器滾動(dòng)方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11

