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>