Angular 的路由守卫指的是,从一个路径跳转到另一个路径之前,执行指定的逻辑,并根据执行结果来决定是否进行跳转。
最典型的例子就是,只有在登录页面填写正确的账号和密码,才被允许导航到内容页面,否则不会进行跳转。
为了实现这个功能,Angular 提供了激活拦截的功能,也就是当路由被激活时,将获得通知。
项目截图:
首先,创建一个权限服务,该服务实现路由守卫的 canActivate() 接口类,当该方法返回 true 时,表示允许跳转;反之则表示不允许跳转。
auth-gurd.service.ts
import { Injectable } from '@angular/core'; // 导入使用到的接口 import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router'; import { Observable } from 'rxjs'; @Injectable() // 实现 CanActivate 接口 export class AuthGurdService implements CanActivate { constructor( private router: Router ) { } canActivate(route: ActivatedRouteSnapshot, // 激活路由的配置项 state: RouterStateSnapshot) // 路由状态的配置项 // 函数返回值可以是 boolean、UrlTree、Observable、Promise : boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> { console.log(route); console.log(state); return this. checkLogin(); } checkLogin(){ if (localStorage.getItem('name') && localStorage.getItem('password')) { return true; } this.router.navigate(['/login']); return false; } }
然后,为了使用这个路由守卫,注入该服务并在路由配置中使用该服务:
app-routing.module.ts
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; // 导入路由守卫 import { AuthGurdService } from './common/auth/auth-gurd.service'; const routes: Routes = [ { path: '', redirectTo: '/login', pathMatch: 'full' }, { path: 'login', loadChildren: () => import('./login/login.module').then((m) => m.LoginModule), }, // 在 canActivate 属性中配置路由守卫 { path: 'main', canActivate: [AuthGurdService], loadChildren: () => import('./main/main.module').then((m) => m.MainModule), } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], // 注入路由守卫 providers: [AuthGurdService], }) export class AppRoutingModule { }
现在,在浏览器中打开该应用时,我们可以看到登录页面。
在表单中输入账号密码,点击登录按钮,将会跳转至内容页面,否则什么也不会发生。
*上面的例子中,路由守卫的方法 canActivate(),除了返回布尔值还可以返回 Observable 和 Promise 对象,这两个对象使得路由守卫可以根据异步处理结果来进行判断。
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) : boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> { return new Promise((done, fail) => { setTimeout(()=>{ if(this.checkLogin()){ done(true); }else{ fail(false); } },2000); }); }
除了上面介绍的激活拦截,Angular 还提供了数据预加载拦截(实现 Resolve 接口)和模块加载拦截(实现 Canload 接口)。
数据预加载拦截适用于对数据进行预加载,当确认数据加载成功后,再激活目标组件。
模块加载拦截适用于惰性加载的路由配置,当路径匹配到该路由时,动态判断是否对该模块进行加载。
数据预加载拦截与模块加载拦截在实际工作中,应用较少,在此就不展开了。
end