辅助路由
激活后,在任何页面都会显示相关的辅助路由组件。
辅助路由的语法分3步
1.页面插座,辅助路由的写法是带有name属性
<router-outlet></router-outlet>
<router-outlet name="aux"></router-outlet>
2.路径配置,名为aux的辅助路由可以用来显示xxx组件和yyy组件
{path:'xxx',component:XxxComponent,outlet:'aux'},
{path:'yyy',component:YyyComponent,outlet:'aux'}
3.路由参数跳转路由,primary控制主路由,不管在哪个页面,点击后主路由都会显示home组件
<a [routerLink]="[{outlets:{primary:'home',aux:'xxx'}}]">开始咨询</a>
主路由-辅助路由。路由的配置:名为aux的辅助路由可以显示xxx和yyy组件。点击Xxx时,主路由显示home组件,辅助路由显示xxx组件
一个辅助路由demo:
//app.component.html
<a [routerLink]="[{outlets:{primary:'home',aux:'consult'}}]">开始咨询</a>
<!-- <a (click)="aux()">开始咨询(这是另一种跳转方式)</a> -->
<a [routerLink]="[{outlets:{aux:null}}]">停止咨询</a>
<router-outlet></router-outlet>
<router-outlet name="aux"></router-outlet>
//routes
{path:'consult',component:ConsultComponent,outlet:'aux'}
使用router跳转的写法
//app.component.ts
aux(){
this.router.navigate([{outlets:{primary:'home',aux:'consult'}}]);
}
路由守卫
也就是,拦截器,在进入或离开路由前执行一些逻辑
- CanActivate : 处理导航到某路由之前的情况,如:付费用户
- CanDeactivate : 处理从当前路由离开的情况,如:是否未保存就离开
- Resolve : 在路由激活之前获取路由数据,提高用户体验
路由守卫语法:
CanActivate
一个用来定义类的接口,路由器会首先调用它来决定是否应该激活该组件。应该返回布尔值或能解析为布尔值的可观察对象(Observable)或承诺(Promise)。
class CanActivateGuard implements CanActivate {
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean>|Promise<boolean>|boolean { ... }
}
{ path: ..., canActivate: [CanActivateGuard] }
返回布尔值为true时进入路由
canActivate demo
//1.编写CanActivate守卫PermissionGuard
// 在guard/permission.guard.ts中
//导入CanActivate守卫
import { CanActivate } from '@angular/router';
export class PermissionGuard implements CanActivate {
canActivate(){
var hasPermission:boolean = Math.random() > 0.5;
if (!hasPermission) {
console.log('用户无权限访问');
};
return hasPermission;
//返回值true时进入路由
}
}
//2.在路由配置中增加canActivate属性
// 在app-routing.module.ts中
//导入PermissionGuard
import { PermissionGuard } from './guard/permission.guard';
const routes: Routes = [{path:'stocks/:id',component:StocksComponent,canActivate:[PermissionGuard]}]
//3.写入providers
// 在app.module.ts中
//先导入
import { PermissionGuard } from './guard/permission.guard';
providers: [PermissionGuard]
Tips : CanActivate在引入接口时首字母大写,其他都是首字母小写canActivate
CanDeactivate
一个用来定义类的接口,路由器在导航后会首先调用它来决定是否应该取消该组件的激活状态。应该返回布尔值或能解析为布尔值的可观察对象(Observable)或承诺(Promise)。
class CanDeactivateGuard implements CanDeactivate<T> {
canDeactivate(
component: T,
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean>|Promise<boolean>|boolean { ... }
}
{ path: ..., canDeactivate: [CanDeactivateGuard] }
返回布尔值为true时离开路由
CanDeactivate demo
//1.编写CanDeactivate守卫focusGuard
// 在guard/permission.guard.ts中
//导入CanDeactivate守卫和要离开的组件
import { CanDeactivate } from '@angular/router';
import { StocksComponent } from '../stocks/stocks.component';
//判断component上isfocus是否已关注,未关注就弹出窗口
export class focusGuard implements CanDeactivate<StocksComponent> {
canDeactivate(component:StocksComponent){
if(!component.isfocus){
return window.confirm('不关注吗')
}else{
return true;
}
}
}
//2.在stocks.component.html (要守卫的组件)上写按钮
<button (click)="focus()">关注</button>
//3.在stocks.component.ts 写逻辑
focus(){
this.isfocus = true;
}
//4.在路由配置中增加canDeactivate属性
// 在app-routing.module.ts中
//5.导入focusGuard
import { focusGuard } from './guard/focus.guard';
const routes: Routes = [{path:'stocks/:id',component:StocksComponent,canActivate:[PermissionGuard],canDeactivate:[focusGuard]}]
//6.写入providers
// 在app.module.ts中
//先导入
import { focusGuard } from './guard/focus.guard';
providers: [PermissionGuard,focusGuard]
Resolve
一个用来定义类的接口,路由器会在渲染该路由之前先调用它来解析路由数据。应该返回一个值或能解析为值的可观察对象(Observable)或承诺(Promise)。
class ResolveGuard implements Resolve<T> {
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any>|Promise<any>|any { ... }
}
{ path: ..., resolve: [ResolveGuard] }
将返回的数据带入路由
Resolve demo
在进入路由{path:”stock/:id”}时,当id=1时,实例化stock类
//1.在stockComponent中编写stock类的构造函数
export class StocksComponent implements OnInit {
private stock:Stock;
constructor() { }
ngOnInit() {
}
}
export class Stock{
constructor(public id:number,public name:string){}
}
//2.编写Resolve:stockResolve,返回值将传入对应path的Resolve属性中,当id=1时,实例化stock并返回
//注意导入的内容
import { Resolve,ActivatedRouteSnapshot,RouterStateSnapshot,Router } from '@angular/router';
import { Stock } from '../stocks/stocks.component';
import { Observable } from 'rxjs';
import { Injectable } from '@angular/core';
//@Injectable() 使constructor中的依赖注入生效,组件有@Component注解所以不用写@Injectable()
@Injectable()
export class stockResolve implements Resolve<Stock>{
constructor(private router:Router){}
resolve(route: ActivatedRouteSnapshot,state: RouterStateSnapshot): Observable<Stock>|Promise<Stock>|Stock {
let id = route.params['id'];
//路由路径id为1时
if(id == 1){
console.log('这里是1');
return new Stock(1,'IBM'); // 返回实例化值 stock
}else{
this.router.navigate(['/home']);
return undefined;
}
}
}
//3.在路由配置中,path路径中增加Resolve属性:
{path:'stocks/:id',component:StocksComponent,canActivate:[PermissionGuard],canDeactivate:[focusGuard],resolve:{stock:stockResolve}
//resolve对象格式,各种数据。stockResolve守卫传值给stock
}
//4.在stockComponent中的ngOnInit,data数据值来源于path中的stock,stock是Stock类型
ngOnInit() {
this.routerInfo.data.subscribe((data:{stock:Stock})=>{
this.stock = data.stock
console.log(this.stock);
});
}
//5.在provider中写入stockResolve
//先导入
import { stockResolve } from './guard/stock.resolve';
providers: [PermissionGuard,focusGuard,stockResolve ]
Tips:注意Resolve的导入内容和依赖注入时需使用@Injectable()
你的负担将变成礼物,你受的苦将照亮你的路。 ——泰戈尔