react实现路由跳转拦截功能(导航守卫)
react實(shí)現(xiàn)路由跳轉(zhuǎn)攔截功能(導(dǎo)航守衛(wèi))
- 背景
- 方法1:通過Prompt組件實(shí)現(xiàn)react路由跳轉(zhuǎn)攔截功能
- Prompt組件介紹
- Prompt組件示例
- 自定義Prompt組件的提示彈窗
- 方法2:通過history.block實(shí)現(xiàn)react路由跳轉(zhuǎn)攔截功能
- history.block介紹
- history.block基本示例
- history.block使用示例(自定義彈窗)
- 文章參考
背景
最近接到一個需求,當(dāng)用戶將要離開指定頁面的時候,需要攔截頁面的跳轉(zhuǎn),并彈出提示框,提醒用戶去做某一項(xiàng)操作(比如數(shù)據(jù)的保存和提交),只有當(dāng)用戶完成操作之后,或者關(guān)閉提示窗,才能離開此頁面進(jìn)行下一頁面的跳轉(zhuǎn)。
這樣的需求,通常做法是:監(jiān)聽路由的跳轉(zhuǎn)操作,阻塞跳轉(zhuǎn),實(shí)現(xiàn)攔截,并在用戶處理完需要的操作之后(如數(shù)據(jù)保存、提交、關(guān)閉彈窗),才放開跳轉(zhuǎn)權(quán)限,允許用戶跳轉(zhuǎn)下一頁面。
方法1:通過Prompt組件實(shí)現(xiàn)react路由跳轉(zhuǎn)攔截功能
如果前端項(xiàng)目是使用vue來編寫,我們可以很快處理這一問題,因?yàn)関ue自帶的導(dǎo)航守衛(wèi)Api如beforeRouteLeave就可以實(shí)現(xiàn)該功能。
但是react并沒有提供像vue一樣的導(dǎo)航守衛(wèi)Api,因此我們需要另辟蹊徑。react-router-dom提供了Prompt組件,通過在需要進(jìn)行路由跳轉(zhuǎn)攔截的頁面的任意地方加上Prompt組件,我們都能實(shí)現(xiàn)路由跳轉(zhuǎn)攔截。
Prompt組件介紹
<Prompt when={true} message={(location) => { return '信息還沒保存,確定離開嗎?' }} />Prompt接受兩個屬性:
when(非必傳),數(shù)據(jù)類型為boolean值。
when=true時,阻塞路由跳轉(zhuǎn)(如果message為字符串或者message的方法返回字符串,還會彈出提示彈窗,彈窗信息為message的字符串值或者message方法返回的字符串);
when=false,不阻塞路由跳轉(zhuǎn),也不彈出提示彈窗(當(dāng)when=false時,即使message為字符串或者message的方法返回字符串,也不會彈出提示窗)。
注意:只有當(dāng)when=true的時候,才會執(zhí)行message的方法。
message(必傳),數(shù)據(jù)類型可以是字符串或方法
message可以是字符串或方法,如果message為方法,那么該方法會接收一個location參數(shù),參數(shù)包含將要跳轉(zhuǎn)的下一個路由的路徑等信息(如果message為方法,那么該方法主要用于處理路由攔截后的操作)。
前提是當(dāng)when=true時,message為字符串,則會阻塞路由并彈出提示彈窗,彈窗內(nèi)容為message字符串。
前提是當(dāng)when=true時,message為方法,當(dāng)方法返回true就順利跳轉(zhuǎn);返回false則阻塞路由跳轉(zhuǎn)(不會彈出提示彈窗);當(dāng)方法返回字符串就阻塞路由跳轉(zhuǎn),并彈出提示彈窗,彈窗提示內(nèi)容為方法返回的字符串。
Prompt對路由攔截的作用只會作用于其所掛載的當(dāng)前路由,當(dāng)跳轉(zhuǎn)到另一個路由(或者Prompt組件被銷毀的時候),該P(yáng)rompt組件將不會再對路由跳轉(zhuǎn)有攔截作用,除非重新掛載和初始化Prompt組件
Prompt組件示例
接下來我們看看在react中如何使用Prompt組件實(shí)現(xiàn)路由攔截:
頁面上任意位置掛載Prompt 組件,點(diǎn)擊“路由跳轉(zhuǎn)”按鈕,觸發(fā)路由跳轉(zhuǎn)事件
接下來我們看看Prompt組件的when和message屬性的不同屬性值,在觸發(fā)路由跳轉(zhuǎn)時,會發(fā)生什么:
① 只賦值when屬性,不賦值message屬性,頁面會報錯,提示message屬性應(yīng)必傳
<Prompt when={true} />
② when=true,message為字符串,當(dāng)觸發(fā)路由跳轉(zhuǎn)事件時,路由跳轉(zhuǎn)會被攔截,并彈出提示窗,提示信息為message的值,點(diǎn)擊提示窗確定按鈕,路由被釋放,跳轉(zhuǎn)到指定頁面;點(diǎn)擊取消按鈕,路由跳轉(zhuǎn)被取消,同時關(guān)閉提示窗
③ when=false,message為字符串,當(dāng)觸發(fā)路由跳轉(zhuǎn)事件時,路由跳轉(zhuǎn)不會被攔截,路由會跳轉(zhuǎn)到指定頁面。這是因?yàn)?font color="red">只有當(dāng)when=true的時候,才會執(zhí)行message的方法。
④ when=true,message為方法,且方法返回值為字符串,當(dāng)觸發(fā)路由跳轉(zhuǎn)事件時,路由跳轉(zhuǎn)會被攔截,并彈出提示窗,提示信息為message的方法返回的字符串,點(diǎn)擊提示窗確定按鈕,路由被釋放,跳轉(zhuǎn)到指定頁面;點(diǎn)擊取消按鈕,路由跳轉(zhuǎn)被取消,同時關(guān)閉提示窗
<Prompt when={true} message={(location) => {return '信息還沒保存,確定離開嗎?'}} />
⑤ when=false,message為方法,且方法返回值為字符串,同時message方法內(nèi)還包含如console.log(‘跳轉(zhuǎn)’)語句。當(dāng)觸發(fā)路由跳轉(zhuǎn)事件時,路由跳轉(zhuǎn)不會被攔截,路由會跳轉(zhuǎn)到指定頁面。且message方法未被執(zhí)行。這是因?yàn)?font color="red">只有當(dāng)when=true的時候,才會執(zhí)行message的方法。
⑥ when=true,message為方法,且方法返回值為true,同時message方法內(nèi)還包含如console.log(‘跳轉(zhuǎn)’)語句。當(dāng)觸發(fā)路由跳轉(zhuǎn)事件時,message方法會被執(zhí)行,路由跳轉(zhuǎn)不會被攔截,路由會跳轉(zhuǎn)到指定頁面。
<Prompt when={true} message={(location) => {console.log(location, '跳轉(zhuǎn)');return true; }} />
⑦ when=true,message為方法,且方法返回值為false,同時message方法內(nèi)還包含如console.log(‘跳轉(zhuǎn)’)語句。當(dāng)觸發(fā)路由跳轉(zhuǎn)事件時,message方法會被執(zhí)行,路由跳轉(zhuǎn)會被攔截,但不會彈出提示框。
⑧ 接下來我們演示一下項(xiàng)目中通過Prompt組件攔截用戶跳轉(zhuǎn)路由。
需求:
做法:
Prompt的when屬性值變量放于state中,message賦值為方法
注意:
當(dāng)when的屬性值,初始化必須為true,否則阻塞不了路由跳轉(zhuǎn)。因?yàn)閟etState是異步操作
效果:
當(dāng)用戶點(diǎn)擊“路由跳轉(zhuǎn)”按鈕,阻塞路由跳轉(zhuǎn),彈出提示窗,提示內(nèi)容為message的函數(shù)返回的字符串,當(dāng)用戶點(diǎn)擊“保存信息”按鈕后,再次點(diǎn)擊路由跳轉(zhuǎn)按鈕,路由成功跳轉(zhuǎn),不再彈出提示窗
自定義Prompt組件的提示彈窗
從上述示例我們可以看到,Prompt阻塞路由跳轉(zhuǎn)之后彈出的提示彈窗,樣式是系統(tǒng)默認(rèn)的,我們并不可以修改,那么我們能不能自定義提示彈窗呢?接下來我們演示一下如何自定義Prompt的提示彈窗
需求:
做法:
Prompt的when屬性值變量放于state中,message賦值為方法。其中message方法主要用于處理路由攔截后的操作,為了不讓默認(rèn)的系統(tǒng)彈窗彈出,而是彈出我們自己的自定義彈窗,因此這時候message方法只能始終return false。這樣的話,我們主要操作Prompt的when屬性值變化,來攔截或者釋放路由的跳轉(zhuǎn)。
注意:
當(dāng)when的屬性值,初始化必須為true,否則阻塞不了路由跳轉(zhuǎn),因?yàn)閟etState是異步操作;同時,當(dāng)setState改變when的屬性值之后,因?yàn)閟etState是異步操作,需要在setState的回調(diào)上手動跳轉(zhuǎn)指定頁面的路由,這樣才能在處理完業(yè)務(wù)邏輯之后,立馬同步跳轉(zhuǎn)路由,否則由于是異步更新state,用戶需要點(diǎn)擊兩次跳轉(zhuǎn)按鈕才能跳轉(zhuǎn)路由。
方法2:通過history.block實(shí)現(xiàn)react路由跳轉(zhuǎn)攔截功能
history.block介紹
我們可用withrouter把histroy注入props,用history.block阻塞路由跳轉(zhuǎn)。
當(dāng)history.block的回調(diào)函數(shù)返回true,則釋放路由跳轉(zhuǎn);
當(dāng)history.block的回調(diào)函數(shù)返回false,則阻塞路由跳轉(zhuǎn),不彈出彈窗;
當(dāng)history.block的回調(diào)函數(shù)返回字符串,則阻塞路由跳轉(zhuǎn),彈出彈窗,彈窗提示信息為回調(diào)函數(shù)的返回字符串
history.block的回調(diào)函數(shù)接受location參數(shù),location參數(shù)包含即將要跳轉(zhuǎn)到指定路徑的路由信息
千萬要注意的是:history.block的作用對項(xiàng)目是全局影響的,只要history.block初始化一次,就會對所有的路由跳轉(zhuǎn)做攔截,即使跳出了當(dāng)前路由,在另一個路由做跳轉(zhuǎn)的時候,history.block依舊會生效,并起到路由攔截作用。如果想取消history.block的路由跳轉(zhuǎn)攔截作用,只有對其重新初始化,讓其回調(diào)函數(shù)return true,所以通常做法是,在組件的componentWillUnmount這一生命周期對history.block重新初始化,讓其回調(diào)函數(shù)return true,取消history.block的路由跳轉(zhuǎn)攔截作用
history.block基本示例
接下來我們看看在react中如何使用history.block實(shí)現(xiàn)路由攔截:
在組件的componentDidMount生命周期中初始化history.block,其回調(diào)函數(shù)返回字符串,這會使得在該頁面做路由跳轉(zhuǎn)的時候會被攔截,并彈出提示窗,提示信息為其回調(diào)函數(shù)返回的字符串
在組件的componentWillUnmount這一生命周期對history.block重新初始化,讓其回調(diào)函數(shù)return true,取消history.block的路由跳轉(zhuǎn)攔截作用,防止其影響其他頁面做路由跳轉(zhuǎn)
import React, { Component } from 'react'; import { Button } from 'antd'; import { withRouter } from 'react-router-dom';class index extends Component {state = {}componentDidMount() {this.props.history.block(location => { // 當(dāng)history.block的回調(diào)函數(shù)返回true,則釋放路由跳轉(zhuǎn);當(dāng)history.block的回調(diào)函數(shù)返回false,則阻塞路由跳轉(zhuǎn),不彈出彈窗;當(dāng)history.block的回調(diào)函數(shù)返回字符串,則阻塞路由跳轉(zhuǎn),彈出彈窗,彈窗提示信息為回調(diào)函數(shù)的返回字符串(點(diǎn)擊確定,釋放路由,繼續(xù)跳轉(zhuǎn)到指定頁面,點(diǎn)擊取消,關(guān)閉彈窗,繼續(xù)阻塞路由跳轉(zhuǎn))console.log(location) // history.block的回調(diào)函數(shù)接手location參數(shù),location參數(shù)包含即將要跳轉(zhuǎn)到指定路徑的路由信息// return true;// return false;return '信息還沒保存,確定離開嗎?'});}componentWillUnmount() { // history.block的作用對項(xiàng)目是全局影響的,組件的componentWillUnmount一定要記得重新初始化history.block,讓其回調(diào)函數(shù)返回true,取消history.block的路由跳轉(zhuǎn)攔截作用,防止其影響其他頁面做路由跳轉(zhuǎn)this.props.history.block(location => { // 當(dāng)history.block的回調(diào)函數(shù)返回true,則釋放路由跳轉(zhuǎn);當(dāng)history.block的回調(diào)函數(shù)返回false,則阻塞路由跳轉(zhuǎn),不彈出彈窗;當(dāng)history.block的回調(diào)函數(shù)返回字符串,則阻塞路由跳轉(zhuǎn),彈出彈窗,彈窗提示信息為回調(diào)函數(shù)的返回字符串(點(diǎn)擊確定,釋放路由,繼續(xù)跳轉(zhuǎn)到指定頁面,點(diǎn)擊取消,關(guān)閉彈窗,繼續(xù)阻塞路由跳轉(zhuǎn))console.log(location) // history.block的回調(diào)函數(shù)接手location參數(shù),location參數(shù)包含即將要跳轉(zhuǎn)到指定路徑的路由信息return true;// return false;// return '信息還沒保存,確定離開嗎?'});}// 跳轉(zhuǎn)路由handleRouterSwitch = () => {this.props.history.push('/outside')}render() {return (<div><Button onClick={this.handleRouterSwitch}>跳轉(zhuǎn)路由</Button></div>)} }export default withRouter(index);點(diǎn)擊“路由跳轉(zhuǎn)”按鈕,觸發(fā)路由跳轉(zhuǎn)事件,history.block阻塞路由跳轉(zhuǎn),并彈出提示窗,提示信息為history.block回調(diào)函數(shù)return的字符串
點(diǎn)擊彈窗“確定”按鈕,釋放路由,繼續(xù)跳轉(zhuǎn)到目標(biāo)url
點(diǎn)擊彈窗“取消”按鈕,關(guān)閉彈窗,路由不做跳轉(zhuǎn)
history.block使用示例(自定義彈窗)
從上述示例我們可以看到,history.block阻塞路由跳轉(zhuǎn)之后彈出的提示彈窗,樣式是系統(tǒng)默認(rèn)的,我們并不可以修改,那么我們能不能自定義提示彈窗呢?接下來我們演示一下如何自定義history.block的提示彈窗
需求:
做法:
history.block只有在其回調(diào)函數(shù)返回值為字符串的時候,才會彈出系統(tǒng)彈窗,而返回布爾值的時候,不會彈出彈窗,我們僅僅需要history.block的路由攔截功能,不讓其彈出系統(tǒng)彈窗,而是彈出自定義彈窗,那么我們讓history.block的回調(diào)函數(shù)返回true就可以釋放路由,返回false就可以攔截路由,在返回false的同時,展示自定義的彈窗。通過重新初始化history.block,操作history.block的回調(diào)函數(shù)返回值,來攔截或者釋放路由的跳轉(zhuǎn)。
文章參考
https://www.cnblogs.com/tirybk/p/14688240.html
https://www.cnblogs.com/amiezhang/p/13207409.html
https://github.com/mirrorjs/mirror/issues/78
https://segmentfault.com/a/1190000019105896
https://segmentfault.com/a/1190000020241389?utm_source=tag-newest
https://segmentfault.com/a/1190000039190541
總結(jié)
以上是生活随笔為你收集整理的react实现路由跳转拦截功能(导航守卫)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小学计算机教案2018六年级,2017年
- 下一篇: 收集LOGO生成网站(持续更新)