React實現(xiàn)路由返回攔截的三種方式
背景
最近項目為了避免用戶誤操作導(dǎo)致數(shù)據(jù)丟失,增加返回攔截功能,但是之前由于qiankun
的報錯導(dǎo)致這個功能一直有一些問題,所以專門獨立搞了一個專題研究在react中各種方式實現(xiàn)這個功能,組內(nèi)小伙伴使用的是prompt
方式,實現(xiàn)的還是比較方便,我打算探索另外別的方式實現(xiàn),想用hooks
的方式實現(xiàn)
技術(shù)棧:
- react17
- react-router5
方法一:使用history.block方式實現(xiàn)
場景:需要靈活定制彈框樣式,需要比對跳轉(zhuǎn)地址和當(dāng)前地址
不足:還需要手動放行,并且手動實現(xiàn)跳轉(zhuǎn)
函數(shù)有兩個參數(shù),第一個是一個對象,包含要跳轉(zhuǎn)的地址等信息,第二個是觸發(fā)的動作,包含三個值POP,REPLACE,PUSH
,可以根據(jù)這三個類型,定制開發(fā)一些業(yè)務(wù)邏輯,函數(shù)的返回值是解除限制函數(shù),比如只想回退攔截,手動點擊跳轉(zhuǎn)不攔截,就可以判斷action是POP
的時候返回false
實現(xiàn)方式如下:
useEffect(() => { //這里要緩存函數(shù)返回的方法,返回的函數(shù)是解除限制函數(shù),想解除直接調(diào)用一下 unblockRef.current = history.block((tx, action) => { setTargetPathname(tx.pathname)//緩存目標(biāo)路徑 之所以緩存,是為了彈框點擊確認的時候可以獲取到 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])
下面定義一個自定義的彈框,直接用原生dialog元素寫個
<dialog className="dialog" open={open}> <p>確認離開么<br /></p> <button onClick={cancel}>取消</button> <button onClick={handleConfirm}>確定</button> </dialog>
注意,當(dāng)點擊確認的時候,需要先解除限制,然后再跳轉(zhuǎn)一下之前要跳轉(zhuǎn)的鏈接,官方說有個retry的方法,我一直沒有找到該方法,也可能我的react-router版本低吧
const handleConfirm = () => { setOpen(false) if (unblockRef.current) { unblockRef.current();//釋放限制 } history.push(targetPathname)//從新跳轉(zhuǎn)之前要跳轉(zhuǎn)的頁面 }
方法二:使用prompt結(jié)合message函數(shù)實現(xiàn)自定義彈框
場景: 需要通過開關(guān)控制是否攔截,并需要自定義ui,需要比對跳轉(zhuǎn)地址
不足:當(dāng)點擊通過的時候,如果不延時會存在狀態(tài)更新不及時導(dǎo)致不能正常跳轉(zhuǎn)
prompt接受一個when的參數(shù),true代表攔截 message可以是一個字符串或者是一個函數(shù),如果是字符串則調(diào)用系統(tǒng)默認彈框, 如果想自定義彈框則需要在函數(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)想點擊確認跳轉(zhuǎn)的時候,要先解除限制,然后再手動跳轉(zhuǎn),由于狀態(tài)可能更新不及時,所以設(shè)置幾百毫秒之后再跳轉(zhuǎn)
const handleConfirm = () => { setIsBlock(false) setOpen(false) //需要等待鎖釋放之后才能跳轉(zhuǎn) setTimeout(() => { history.push(targetPathname)//從新跳轉(zhuǎn)之前要跳轉(zhuǎn)的頁面 console.log('確認') }, 100) } const cancel = () => { setOpen(false) }
方法三:基于prompt,修改路由getUserConfirmation實現(xiàn)自定義彈框攔截
場景:需要全局統(tǒng)一樣式,彈框樣式固定,需要靈活控制攔截條件
不足:
由于攔截彈框是在全局進行攔截,所以如果不同頁面要求不同攔截彈框不太好實現(xiàn)
不太好判斷要跳轉(zhuǎn)到的地址和當(dāng)前地址比對
頁面中只需要寫如下,通過一個開關(guān)控制是否攔截,給一個錯誤的提示
<Prompt when={isBlock} message={'自定義---確定你要返回么?。。。?!'}></Prompt>
然后再路由定義的時候增加如下,增加一個getUserConfirmation配置,用來獲取prompt傳過來的攔截消息,并緩存callback函數(shù),這個函數(shù)用來控制是否放行
<Router getUserConfirmation={(message, callback) => { callbackRef.current = callback setMessage(message) setOpen(true) } } >
當(dāng)點擊確認跳轉(zhuǎn)則調(diào)用callback(true)
,點擊取消則調(diào)用callback(false)
,路徑地址就變回來了, callback(true)
不需要再手動跳轉(zhuǎn),會自動跳轉(zhuǎn)
const handleConfirm = () => { setOpen(false) callbackRef.current?.(true) } const cancel = () => { callbackRef.current?.(false) setOpen(false) }
到此這篇關(guān)于React實現(xiàn)路由返回攔截的三種方式的文章就介紹到這了,更多相關(guān)React路由返回攔截內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React父組件數(shù)據(jù)實時更新了,子組件沒有更新的問題
這篇文章主要介紹了React父組件數(shù)據(jù)實時更新了,子組件沒有更新的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03阿里低代碼框架lowcode-engine設(shè)置默認容器詳解
這篇文章主要為大家介紹了阿里低代碼框架lowcode-engine設(shè)置默認容器詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02react高階組件經(jīng)典應(yīng)用之權(quán)限控制詳解
在React中,高階組件是重用組件邏輯的一項高級技術(shù)。下面這篇文章主要給大家介紹了關(guān)于react高階組件經(jīng)典應(yīng)用之權(quán)限控制的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-09-09react ant Design手動設(shè)置表單的值操作
這篇文章主要介紹了react ant Design手動設(shè)置表單的值操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10React-router?v6在Class組件和非組件代碼中的正確使用
這篇文章主要介紹了React-router?v6在Class組件和非組件代碼中的正確使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03全棧輕量級搭配之Remix Prisma Sqlite使用分析
這篇文章主要為大家介紹了全棧輕量級搭配之Remix Prisma Sqlite使用示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05