Angular的常用路由守卫有5种,按照执行顺序:
① CanLoad:进入到当前路由的时候触发(若用户没有权限访问,相应的模块并不会被加载。这里是指对应组件的代码)。
↓
② CanAcitivate:进入到当前路由的时候触发(即使返回的是false,用户并没有权限访问该路由,但是相应的模块会被加载)。
↓
③ CanActivateChild:刚刚进入子路由触发。
↓
④ Resolve:进入当前路由之后,离开之前触发。
↓
⑤ CanDeactivate:离开当前路由离开的时候触发。
① guard/CanLoad.guard.ts
import { Injectable } from '@angular/core'; import { CanLoad, Route, Router, UrlSegment } from '@angular/router'; @Injectable() export class CanLoadGuard implements CanLoad { constructor(private router: Router) { } canLoad( route: Route, segments: UrlSegment[] ) { console.log('【CanLoad守卫:进入当前子路由】----------------------------------------', route, segments); return true;//进入路由 // return false;//中端路由 } }
② guard/CanAcitivate.guard.ts
import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router'; @Injectable({ providedIn: 'root' })//这个在该守卫里面必须要,其余两种守卫中可以不需要 /* 没有上面这句会报错 ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(AppModule)[CanAcitivateGuard -> CanAcitivateGuard -> CanAcitivateGuard]: NullInjectorError: No provider for CanAcitivateGuard! NullInjectorError: R3InjectorError(AppModule)[CanAcitivateGuard -> CanAcitivateGuard -> CanAcitivateGuard]: NullInjectorError: No provider for CanAcitivateGuard! */ export class CanAcitivateGuard implements CanActivate { constructor(private router: Router) { } // 这就是你们想要的路由守卫 canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot ) { console.log('【CanActivate守卫:进入当前路由】----------------------------------------', next, state); // 这里可以做各种路由判断的骚操作,通常我们主要是判断用户登录状态 // 判断本地有没有token,如果token有值,表示登录成功,继续跳转 if (localStorage.token) { return true; } else { //兄嘚!你都没有登录,乖乖去一下登录页面吧~ this.router.navigate(['/login']); return false; } } }
③ guard/CanActivateChild.guard.ts
import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivateChild, Router, RouterStateSnapshot } from '@angular/router'; @Injectable() export class CanActivateChildGuard implements CanActivateChild { constructor(private router: Router) { } canActivateChild( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ) { console.log('【CanActivateChild守卫:进入当前子路由】----------------------------------------', route, state); return true;//进入路由 // return false;//中端路由 } }
④ guard/Resolve.guard.ts
import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router'; import { AppComponent } from '../app.component'; @Injectable() export class ResolveGuard implements Resolve<AppComponent> { constructor(private router: Router) { } resolve( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): any { console.log('【Resolve守卫:进入当前路由之后,离开之前】----------------------------------------', route, state); } }
⑤ guard/CanDeactivate.guard.ts
import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanDeactivate, Router, RouterStateSnapshot } from '@angular/router'; import { AppComponent } from '../app.component'; @Injectable() export class CanDeactivateGuard implements CanDeactivate<AppComponent> { constructor(private router: Router) { } canDeactivate( component: AppComponent, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot ) { console.log('【CanDeactivate守卫:离开当前路由】----------------------------------------', currentRoute, currentState, nextState); return confirm('一旦离开,未保存的内容将丢失!'); } }
app-routing.module.ts
import { CanLoadGuard } from './guard/CanLoad.guard'; import { CanAcitivateGuard } from './guard/CanAcitivate.guard'; import { AppComponent } from './app.component'; import { ResolveGuard } from './guard/Resolve.guard'; import { CanDeactivateGuard } from './guard/CanDeactivate.guard'; import { NgModule } from '@angular/core'; import { RouterModule, Routes, Resolve, Route, UrlSegment } from '@angular/router'; import { HomeComponent } from './com/home/home.component'; import { LoginComponent } from './com/login/login.component'; import { CanActivateChildGuard } from './guard/CanActivateChild.guard'; import { ChildComponent } from './com/home/child/child.component'; const routes: Routes = [ { path: '', component: AppComponent, }, { path: 'home', component: HomeComponent, canLoad: [CanLoadGuard],//顺序1(刚进入路由,还未加载组件) canActivate: [CanAcitivateGuard],//顺序2(刚进入路由,部分组件加载) canActivateChild: [CanActivateChildGuard],//顺序3(刚刚进入子路由)(必须加上这个,否则会报错) resolve: { data: ResolveGuard },//顺序4(进入路由后)(必须加上这个,否则会报错) canDeactivate: [CanDeactivateGuard],//顺序5(离开路由) children: [ { path: 'child', component: ChildComponent, } ] }, { path: 'login', component: LoginComponent, }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], providers: [ /* 【CanActivate 和 CanLoad的区别】 CanActivate:即使返回的是false,用户并没有权限访问该路由,但是相应的模块会被加载。 CanLoad:若用户没有权限访问,相应的模块并不会被加载。这里是指对应组件的代码。 */ CanLoadGuard,//顺序1(刚进入路由,还未加载组件) CanAcitivateGuard,//顺序2(刚进入路由,部分组件加载) CanActivateChildGuard,//顺序3(刚刚进入子路由)(必须加上这个,否则会报错) ResolveGuard,//顺序4(进入路由后)(必须加上这个,否则会报错) CanDeactivateGuard,//顺序5(离开路由) ] }) export class AppRoutingModule { }
访问localhost:4200/home打开F12查看提示:
app.component.html
<router-outlet></router-outlet>
在home里面写一个按钮点击跳转到localhost/,然后打开F12查看
app/home/home.component.ts
import { Router } from '@angular/router'; ... constructor(public router: Router) { } ...
app/home/home.component.html
<button (click)="router.navigate(['/home/child'])">跳转到child,F12去看看CanActivateChild路由守卫结果</button> <br><br> <button (click)="router.navigate(['/login'])">跳转到login,F12去看看CanDeactivate路由守卫结果</button>