基本概念
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