用於肯定是否能夠激活路由。若是全部守衛都返回true
,導航將繼續。若是有任何後衛返回false
,導航將被取消。異步
類能夠實現爲肯定是否能夠激活子路由的後衛的接口。若是全部守衛都返回true
,導航將繼續。若是有任何後衛返回false
,導航將被取消。若是任何防禦返回a UrlTree
,則當前導航被取消,而且新的導航開始UrlTree
從防禦返回。函數
{ path: 'a', component: AComponent, data: {name: 'xxx'}, canActivate: [OneService], canActivateChild:[OneService], children: [ {path:'c/d', component: CComponent} ] }, export class OneService implements CanActivate, CanActivateChild { constructor() {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) : Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { // route 當前快照 console.log(route); // 當前的url // console.log(state.url); return true; } canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { // childRoute 路由的子快照 console.log(childRoute); return true; } }
**canActivate**
存在這種狀況是爲了防止未經受權的用戶訪問路由,而**canLoad**
用於防止應用程序在未經受權的狀況下以延遲方式(延遲加載)加載整個模塊或組件this
{path: 'home', loadChildren: () => import('./three/three.module').then(m => m.ThreeModule), canLoad: [TestService] }, @Injectable() export class TestService implements Resolve<any>,CanActivate,CanDeactivate<any>,CanLoad{ canDeactivate(component: any, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { return of(true) }
觸發順序:url
-canload 加載code
-canActivate 進入(重要)component
這兩種不是寫在一塊兒,因此順序應該不能一律而論router
canActivateChild 進入子路由blog
canDeactivate 離開(重要)接口
canActivate 用於防止未經受權的用戶訪問某些路由three
canLoad 用於防止應用程序(延遲加載)整個模塊
保證了數據獲取後在進行路由跳轉,防止由於數據延遲而出現的空組件狀況
簡單的理解成解決延遲守衛
{ path: 'b', component: BComponent, resolve: {sex: TestService} }, ===== @Injectable() export class TestService implements Resolve<any>{ resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any { return of([1,2,3]) } } ===== export class BComponent implements OnInit, AfterViewInit { constructor( private route:ActivatedRoute ) { this.route.data.subscribe(console.log); // {sex: [1, 2, 3]} } }
先上源碼
function shouldRunGuardsAndResolvers( curr: ActivatedRouteSnapshot, future: ActivatedRouteSnapshot, mode: RunGuardsAndResolvers|undefined): boolean { if (typeof mode === 'function') { return mode(curr, future); } switch (mode) { case 'pathParamsChange': return !equalPath(curr.url, future.url); case 'pathParamsOrQueryParamsChange': return !equalPath(curr.url, future.url) || !shallowEqual(curr.queryParams, future.queryParams); case 'always': return true; case 'paramsOrQueryParamsChange': return !equalParamsAndUrlSegments(curr, future) || !shallowEqual(curr.queryParams, future.queryParams); case 'paramsChange': default: return !equalParamsAndUrlSegments(curr, future); } } export type RunGuardsAndResolvers = 'pathParamsChange'|'pathParamsOrQueryParamsChange'|'paramsChange'|'paramsOrQueryParamsChange'| 'always'|((from: ActivatedRouteSnapshot, to: ActivatedRouteSnapshot) => boolean); 最後一個是自定義函數,返回boolean,用來判斷是否促發守衛
runGuardsAndResolvers
的選項,默認paramsChange
模式
意味着他將從新運行路徑或路徑參數的變化,會觸發變動
變動: 意思是會觸發路由守衛
{ path: 'home/:id', component: HomeComponent, ... runGuardsAndResolvers: 'paramsChange' } 執行 /home/1 => /home/2 /home/1 => /home/1;param1=38 /home/1;param1=38 => /home/1;param1=20 不執行 /home/1 => /home/1?queryParam=hi
爲了方便理解,我寫一個小案例
{ path: 'a', component: AComponent, children: [ { path: 'c/:id', component: CComponent, canActivate: [OneService], } ] }, ==== export class OneService implements CanActivate, CanActivateChild { constructor() { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) : Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { // route 當前快照 console.log('觸發'); // 當前的url // console.log(state.url); return true; } } ==== <a routerLink="/home/a/c/1">c/1</a> <br> <a routerLink="/home/a/c/2">c/2</a> <br> <a routerLink="/home/a/c/3">c/3</a> <br> <a routerLink="/home/a/c/3" [queryParams]="{name:'xxx'}">c/3?name=xxx</a> <br> <a routerLink="/home/a/c/3" [queryParams]="{name:'bbb'}">c/3?name=bbb</a> <br> <a routerLink="/home/a/c/3" [queryParams]="{name:'ccc'}">c/3?name=ccc</a> <br>
咱們會發現問號傳參的,默認路由防禦策略不會執行路由守衛
;name=ccc
)改變時,忽略查詢參數更改