路由守卫,实际意义是拦截器,在你进入路由或离开路由执行一些逻辑。
1.路由守卫有三种:
(1)CanActivate:处理导航到某路由的情况
(2)CanDeactivate:处理从当前路由离开的情况
(3)Resove 在路由激活之前获取路由数据
2.路由守卫实战:
【CanActivate】
第一步:写出CanActivate路由守卫的验证规则
创建文件 app/guard/permission.guard.ts
import {CanActivate} from '@angular/router';
export class PermissionGuard implements CanActivate{
canActivate(){
var hasPermission: boolean = Math.random() < 0.5;
if( !hasPermission )
{
console.log("用户无权访问股票详情");
}
return hasPermission;
}
}
第二步:将路由守卫配置到路由配置,在app-routing.module.ts
import {StockResolve} from './guard/stock.resolve';
const routes: Routes = [
{path: '', redirectTo: '/home', pathMatch: 'full'},
{path: 'home', component: HomeComponent }, // 默认展示HomeComponnet
{path: 'consult', component: ConsultComponent, outlet: 'aux'},
// SellerListComponen只能能显示在aux的插座上
{
path: 'stock/:id', component: StockComponent, data: [{isPro: true}],
children: [
{path: '', component: BuyerListComponent},
{path: 'seller/:id', component: SellerListComponent}
],
canActivate: [PermissionGuard],
},
{path: '**', component: Code404Component}
];
第三步:需要在app.module.ts中提供器上声明 PermissionGuard
providers: [PermissionGuard],
此时 CanActivate路由就此完成。
【CanDeactivate】
第一步:写出CanDeactivate路由守卫的验证规则
import {CanDeactivate} from '@angular/router';
import {StockComponent} from '../stock/stock.component';
export class FocusGuard implements CanDeactivate<StockComponent> {
//StockComponent 表示保护的组件,可以拿到当前的组件
canDeactivate(component: StockComponent) {
if ( component.isFocus() ) {
return true;
}else {
return window.confirm( '不关注就离开吗?' );
}
}
}
(2)需要在StockComponent组件中声明一个isFocus()方法
export class StockComponent implements OnInit {
private focus = false;
constructor(private routeInfo: ActivatedRoute) {}
ngOnInit() {
}
isFocus() {
return this.focus;
}
}
(3)StockComponent 的模板上
<input type="button" (click)="focus=true" value="关注" />
第二步:将路由守卫配置到路由配置,在app-routing.module.ts
const routes: Routes = [
{path: '', redirectTo: '/home', pathMatch: 'full'},
{path: 'home', component: HomeComponent }, // 默认展示HomeComponnet
{path: 'consult', component: ConsultComponent, outlet: 'aux'},
// SellerListComponen只能能显示在aux的插座上
{
path: 'stock/:id', component: StockComponent, data: [{isPro: true}],
children: [
{path: '', component: BuyerListComponent},
{path: 'seller/:id', component: SellerListComponent}
],
canActivate: [PermissionGuard],
canDeactivate: [FocusGuard]
},
{path: '**', component: Code404Component}
];
第三步:需要在app.module.ts中提供器上声明 FocusGuard
providers: [PermissionGuard,FocusGuard],
【Resove】
1.resove守卫要解决的问题:以Stock组件为例
(1)stock.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
@Component({
selector: 'app-stock',
templateUrl: './stock.component.html',
styleUrls: ['./stock.component.css']
})
export class StockComponent implements OnInit {
public stock: Stock;
constructor() {}
ngOnInit() {
}
}
export class Stock {
constructor(public id: number, public name: string) {}
}
(2)模板中
<p>股票stock.id是{{stock.id}}</p>
<p>股票stock.name是{{stock.name}}</p>
此时会报错因为stock为空2.解决问题:
Resove守卫在进入组件之前将stock赋值
第一步:写出Resove路由守卫的验证规则
(1)创建文件 app/guard/stock.resove.ts
import { Router, Resolve, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import {Stock} from '../stock/stock.component';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
@Injectable() //使当前类支持依赖注入,@Componnent()继承了@Injectable()
export class StockResolve implements Resolve<Stock> {
constructor( private router: Router){
//Router 类型的对象可以使用导航 this.router.navigate(['/home']);
}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Stock| Observable<Stock> |Promise<Stock>{
// ActivatedRouteSnapshot类型的对象可以取到路由参数
var id = route.params['id'];
if ( id == 1) {
return new Stock(1,"IBM");
}else {
this.router.navigate(['/home']);
return undefined;
}
}
}
第二步:将路由守卫配置到路由配置,在app-routing.module.ts
const routes: Routes = [
{path: '', redirectTo: '/home', pathMatch: 'full'},
{path: 'home', component: HomeComponent }, // 默认展示HomeComponnet
{path: 'consult', component: ConsultComponent, outlet: 'aux'},
// SellerListComponen只能能显示在aux的插座上
{
path: 'stock/:id', component: StockComponent, data: [{isPro: true}],
children: [
{path: '', component: BuyerListComponent},
{path: 'seller/:id', component: SellerListComponent}
],
// canActivate: [PermissionGuard],
// canDeactivate: [FocusGuard],
resolve:{
stock:StockResolve
}
},
{path: '**', component: Code404Component}
];
第三步:需要在app.module.ts中提供器上声明 StockResove
providers: [PermissionGuard,FocusGuard,StockResolve],
第四步:在stock.component.ts中执行给声明的stock对象赋值
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
@Component({
selector: 'app-stock',
templateUrl: './stock.component.html',
styleUrls: ['./stock.component.css']
})
export class StockComponent implements OnInit {
public stock: Stock;
constructor(private routeInfo: ActivatedRoute) {}
ngOnInit() {
this.routeInfo.data.subscribe((data:{stock:Stock})=>{
this.stock=data.stock;
})
}
}
export class Stock {
constructor(public id: number, public name: string) {}
}
此时 :
(
data
:
{
stock
:
Stock
})里面的stock是app-routing.module.ts中的
resolve:
{stock:StockResolve}中的stock,Stock是类型