淺談Angular路由守衛(wèi)
引言
在企業(yè)應(yīng)用中權(quán)限、復(fù)雜頁(yè)多路由數(shù)據(jù)處理、進(jìn)入與離開(kāi)路由數(shù)據(jù)處理這些是非常常見(jiàn)的需求。
當(dāng)希望用戶離開(kāi)一個(gè)正常編輯頁(yè)時(shí),要中斷并提醒用戶是否真的要離開(kāi)時(shí),如果在Angular中應(yīng)該怎么做呢?
其實(shí)Angular路由守衛(wèi)屬性可以幫我們做更多有意義的事,而且非常簡(jiǎn)單。
什么是路由守衛(wèi)?
Angular 的 Route 路由參數(shù)中除了熟悉的 path、component 外,還包括四種是否允許路由激活與離開(kāi)的屬性。
canActivate
控制是否允許進(jìn)入路由。
canActivateChild
等同 canActivate,只不過(guò)針對(duì)是所有子路由。
canDeactivate
控制是否允許離開(kāi)路由。
canLoad
控制是否允許延遲加載整個(gè)模塊。
例如:
{ path: 'logics', loadChildren: './logics/logics.module#LogicsModule', canLoad: [ AuthGuard ] }
這四個(gè)屬性非常好理解,而且作用各自不同。然后當(dāng)進(jìn)入與離開(kāi)能夠有效控制權(quán)時(shí),對(duì)于前面我提到的若干問(wèn)題,就可以非常好的處理。
如何創(chuàng)建?
四個(gè)屬性雖然名稱不同,但其基本的使用方式非常相近。四種不同守衛(wèi)方式有者四個(gè)不同的接口與之相對(duì)應(yīng)。
| 屬性名 | 接口名 |
|---|---|
| canActivate | CanActivate |
| canActivateChild | CanActivateChild |
| canDeactivate | CanDeactivate<TComponent> |
| canLoad | CanLoad |
canDeactivate 需要指明具體的組件類名以外,其他接口只是將首字母大寫而已。假定需要一個(gè)某個(gè)角色才能訪問(wèn)某些路由,就需要一個(gè) CanActivate 守衛(wèi)類。
@Injectable()
export class CanAdminProvide implements CanActivate {
constructor(private userSrv: UserService, private msg: NzMessageService) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean | Observable<boolean> | Promise<boolean> {
return new Observable((observer) => {
// 擁有 `admin` 角色
if (this.userSrv.hasRole('admin')) {
observer.next(true);
observer.complete();
return;
}
this.msg.error('授權(quán)不足');
observer.next(false);
observer.complete();
});
}
}
每種接口要都需要相應(yīng)的實(shí)現(xiàn)某個(gè)方法,就上而論,繼承 CanActivate 并實(shí)現(xiàn)一個(gè)叫 canActivate 的方法;且返回一個(gè)布爾類型的值。
四種類型守衛(wèi)接口都返回一個(gè)布爾類型值,其實(shí)從這四種參數(shù)的名稱 can 開(kāi)頭就不然理解。
最后,把它運(yùn)用到相應(yīng)的路由上即可,例如:
{ path: 'admin', component: GuardAdminComponent, canActivate: [ CanAdminProvide ] }
當(dāng)然,別忘記注冊(cè) CanAdminProvide 類。
一些實(shí)踐
離開(kāi)時(shí)提醒
四種守衛(wèi)只有一種離開(kāi)類型 canDeactivate,因此:
@Injectable()
export class CanLeaveProvide implements CanDeactivate<GuardComponent> {
constructor (private confirmSrv: NzModalService) {}
canDeactivate(
component: GuardComponent,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot,
nextState?: RouterStateSnapshot): boolean | Observable<boolean> | Promise<boolean> {
return new Observable((observer) => {
this.confirmSrv.confirm({
title: '確認(rèn)要離開(kāi)嗎?',
content: '你已經(jīng)填寫了部分表單離開(kāi)會(huì)放棄已經(jīng)填寫的內(nèi)容。',
okText: '離開(kāi)',
cancelText: '取消',
onOk: () => {
observer.next(true);
observer.complete();
},
onCancel: () => {
observer.next(false);
observer.complete();
}
});
});
}
}
這里返回的是一個(gè) Observable 類型,意味者,在方法體內(nèi)可以做任何事,只需要在結(jié)果中使用:
// 允許 observer.next(true); // 或拒絕 // observer.next(false); observer.complete();
來(lái)處理 Observable 的結(jié)果,就完成了整個(gè)流程。倘若,用戶按瀏覽器后退或路由至其他頁(yè)面時(shí),會(huì)先收到一個(gè)提醒。
上面使用的 ng-zorro-antd 的確認(rèn)對(duì)話框來(lái)提醒用戶是否需要離開(kāi),若選擇【離開(kāi)】則跳轉(zhuǎn)至目標(biāo)路由,反之保留當(dāng)前路由狀態(tài)。

角色受限
這是再正常不過(guò)的功能,若用戶進(jìn)入一個(gè)未授權(quán)的路由時(shí),甚至是某個(gè)遲延加載模塊下所有路由;若用戶無(wú)權(quán)限時(shí),如何提醒用戶。
此時(shí) canActivate、canLoad 就有用了。假定管理員角色才能加載管理模塊下所有管理功能以及某個(gè)管理頁(yè)面,基于接口多繼承的特性,可以同時(shí)繼承這兩個(gè)接口。
@Injectable()
export class CanAuthProvide implements CanActivate, CanLoad {
constructor(private userSrv: UserService, private msg: NzMessageService) {}
check(): Observable<boolean> {
return new Observable((observer) => {
if (this.userSrv.isLogin) {
observer.next(true);
observer.complete();
return;
}
this.msg.error('權(quán)限不足');
observer.next(false);
observer.complete();
});
}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean | Observable<boolean> | Promise<boolean> {
return this.check();
}
canLoad(route: Route): boolean | Observable<boolean> | Promise<boolean> {
return this.check();
}
}
因此,一個(gè)類中具有兩種不同守衛(wèi)的能力,更對(duì)于代碼組織也更優(yōu)雅。同樣,需要運(yùn)用到相應(yīng)的路由當(dāng)中。
{ path: 'auth', component: GuardAuthComponent, canActivate: [ CanAuthProvide ] },
{ path: 'admin', loadChildren: './admin/admin.module#AdminModule', canLoad: [ CanAuthProvide ] }
此后,若一個(gè)普通員工賬號(hào)要想進(jìn)入(哪怕瀏覽器地址欄錄入)未授權(quán)的路由 /auth 會(huì)提示 權(quán)限不足 的字樣。

總結(jié)
路由守衛(wèi)對(duì)于權(quán)限控制非常便利,當(dāng)然其粒度當(dāng)然只能在頁(yè)面層級(jí)。倘若需要對(duì)按鈕粒度也只能利用指令的方式,而二者的結(jié)合可以極大的改善權(quán)限控制埋點(diǎn)的代碼量。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
angular實(shí)現(xiàn)表單驗(yàn)證及提交功能
這篇文章主要為大家詳細(xì)介紹了angular實(shí)現(xiàn)表單驗(yàn)證及提交功能的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
詳解AngularJs路由之Ui-router-resolve(預(yù)加載)
本篇文章主要介紹了詳解AngularJs路由之Ui-router-resolve(預(yù)加載),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
Angular組件庫(kù)ng-zorro-antd實(shí)現(xiàn)radio單選框選擇
這篇文章主要為大家介紹了Angular組件庫(kù)ng-zorro-antd實(shí)現(xiàn)radio單選框取消選擇實(shí)現(xiàn)問(wèn)題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
angular學(xué)習(xí)之從零搭建一個(gè)angular4.0項(xiàng)目
本篇文章主要介紹了從零搭建一個(gè)angular4.0項(xiàng)目,主要用到的工具angular4.0、angular-cli、npm(v3.10.8)、node(v6.2.0),有興趣的可以了解一下2017-07-07
Angular8 實(shí)現(xiàn)table表格表頭固定效果
這篇文章主要介紹了Angular8 實(shí)現(xiàn)table表格表頭固定效果,表頭固定,內(nèi)部實(shí)現(xiàn)滾動(dòng)條效果,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-01-01
Angular重構(gòu)數(shù)組字段的解決方法示例
這篇文章主要為大家介紹了Angular重構(gòu)數(shù)組字段的解決方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
將Angular單項(xiàng)目升級(jí)為多項(xiàng)目的全過(guò)程
有時(shí)候在開(kāi)發(fā)的過(guò)程中發(fā)現(xiàn)一個(gè)Angular項(xiàng)目不太夠用,兩個(gè)獨(dú)立的項(xiàng)目又不太好復(fù)用,這時(shí)便需要將原來(lái)的Angular項(xiàng)目簡(jiǎn)單做個(gè)升級(jí),這篇文章主要給大家介紹了關(guān)于將Angular單項(xiàng)目升級(jí)為多項(xiàng)目的相關(guān)資料,需要的朋友可以參考下2021-11-11

