简述
ng的文档不得不说写的很好很全,但就是这个很好很全对入门要求很高,我其实只需要有份最简单的代码示例先把功能跑起来就可以了,至于原理可以在实践中慢慢体会。
路由是实现单页应用的灵魂,可以让我们在应用的模块肆意间肆意穿梭,可问题也就出现在“肆意”上,作为应用的开发者我们肯定是想让用户按照我们的意愿来使用程序,所以比如限制无权限用户进入某些模块,在表单页面离开时,询问用户是否保存,就是我们需要考虑的东西,所幸ng提供了路由守卫这个东西,让我们很容易管理我们模块间的导航。
接下里就是不说原理,纯上代码,跑起程序最重要,原理看ng官网就好了
代码基于ng8
CanActivate:要求认证
首先假设我们有个can-activate页面需要权限才能进入
- 路由配置方面
根路由
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [
{
path: 'can-activate',
loadChildren: () => import('./pages/can-activate/can-activate.module').then(mod => mod.CanActivateModule)
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
模块路由
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import {CanActivateComponent} from './can-activate.component';
import {AuthGuard} from '../../services/others/auth/auth.guard';
import {CanDeactivateGuard} from '../../services/others/can-deactivate/can-deactivate.guard';
const routes: Routes = [
{
path: '',
component: CanActivateComponent,
canActivate: [AuthGuard], // 进入认证
canDeactivate: [CanDeactivateGuard] // 离开认证
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class CanActivateRoutingModule { }
- 设置AuthGuard
import { Injectable } from '@angular/core';
import {ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, UrlTree} from '@angular/router';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
// 下面 这俩行 用来实现业务代码就行了
// 登录失败跳转到统一处理页面 还需要把失败的连接(state.url)带过去 处理成功了 在跳过去
const auth = Math.random() > 0.5;
console.log(`${auth ? '允许登录' : '拒绝登录'}到${state.url}`);
return auth;
}
}
- 至此 can-activate路由完成 就是这么简单,写好一个auth服务,然后在路由里面配置一下就可以了,同理ng的其他路由守卫也是这么个套路
CanDeActivate:处理未保存的更改
- 路由配置如上
- CanDeActivateGuard设置
import { Injectable } from '@angular/core';
import {ActivatedRouteSnapshot, CanDeactivate, RouterStateSnapshot, UrlTree} from '@angular/router';
import { Observable } from 'rxjs';
import {CanActivateComponent} from '../../../pages/can-activate/can-activate.component';
@Injectable({
providedIn: 'root'
})
export class CanDeactivateGuard implements CanDeactivate<CanActivateComponent> {
canDeactivate(component: CanActivateComponent) {
// 这里的component就是需要做守卫的组件 组件里面需要有一个方法来判断当前用户是否可以离开 我们这里叫canDeactivate()
return component.canDeactivate ? component.canDeactivate() : true;
}
}
- 我们再来看 component里面的canDeactivate() 方法
import {DialogService} from '../../services/others/dialog/dialog.service';
@Component({
selector: 'app-can-activate',
templateUrl: './can-activate.component.html',
styleUrls: ['./can-activate.component.less']
})
export class CanActivateComponent implements OnInit {
constructor(public dialogService: DialogService) { }
canDeactivate(): Observable<boolean> | boolean {
// 这里处理业务逻辑 如果业务不通过就return 通过就不返回任何东西 dialogService可以单独做个服务也可以不需要
return this.dialogService.confirm('路由守卫:离开测试');
}
ngOnInit() {
}
}
- 至此 can-acdetivate守卫也完成了。但是代码中的CanDeActivateGuard是针对某一个组件的示例,如果要要成通用的 代码如下
import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { Observable } from 'rxjs';
// 这里 需要这么个接口 不是单独某一个组件
export interface CanComponentDeactivate {
canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}
@Injectable({
providedIn: 'root',
})
export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
canDeactivate(component: CanComponentDeactivate) {
return component.canDeactivate ? component.canDeactivate() : true;
}
}