用于肯定是否能够激活路由。若是全部守卫都返回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
)改变时,忽略查询参数更改