碎碎念:知识点梳理归纳,如果有什么不对的感谢大家指正一起学习!
一、路由守卫
当用户满足一些条件的时候才会被允许进入或者离开一些路由
-
canActivate :处理导航到某路由的情况
当满足导航到此路由的条件时才允许进入路由 -
canDeactivate:处理从当前路由离开的情况
当不满足导航离开路由的条件时不允许离开路由 -
resolve:在路由激活之前获取路由数据
在进入路由时就可以立刻把数据展示给用户
1. canActivate
例:判断当用户是否登录才能进入产品信息路由
(模拟登陆:当随机数小于0.5时为登陆状态)
第一步:创建拦截守卫
// 新建的LoginGuard 文件,实现框架CanActivate 接口
import { CanActivate } from '@angular/router';
export class LoginGuard implements CanActivate {
canActivate() {
let isLogin = Math.random() < 0.5;
if(!isLogin){
console.log("大于0.5,未登陆")
}
return isLogin //返回一个boolean值
}
}
第二步:在路由配置中添加canActivate属性,并在providers中声明
(加在产品信息路由上)
const routes: Routes = [
{
path: 'product/:id', component: ProductComponent,
children: [
{ path: '', component: ProductDescComponent },
{ path: 'seller/:id', component: SellerInfoComponent }
],
canActivate:[LoginGuard] // 接收一个数组,可以接受多个路由守卫
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers:[LoginGuard]
})
canActivate:[LoginGuard] :当应用视图进入此路由时,里面的守卫会被依次调用,只要有一个守卫返回false,路由请求会被拒绝
效果预览:
打开页面在主页home页,我们在进入商品详情1的时候就会进行验证,如果守卫中的随机数大于0.5会跳转失败,并在控制台打印提示信息。如果小于0.5就成功进入商品详情页。
2. canDeactivate
例:用户离开当前路由时提示是否离开
第一步:创建离开守卫文件
// 新建的UnSaveGuard 文件,实现框架CanDeactivate 接口
import { ProductComponent } from '../product/product.component';
import { CanDeactivate } from '@angular/router';
export class UnSaveGuard implements CanDeactivate<ProductComponent> {
canDeactivate(component: ProductComponent) {
return window.confirm("还未保存,确定离开?")
}
}
CanDeactivate有个一泛型,泛型是指定当前组件类型(要保护的组件类型)。
第一个参数泛型类型的组件(把要保护的组件信息传进来)
第二步:在路由配置中添加canDeactivate属性,并在providers中声明
(加在产品信息路由上)
const routes: Routes = [
{
path: 'product/:id', component: ProductComponent,
children: [
{ path: '', component: ProductDescComponent },
{ path: 'seller/:id', component: SellerInfoComponent }
],
canDeactivate:[UnsaveGuard] // 接收一个数组,可以接受多个路由守卫
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers:[UnsaveGuard]
})
效果预览:
从home页成功进入‘商品详情1’的路由后,从商品详情离开会弹出提示是否离开
3. resolve
resolve守卫在进入路由之前可以预先去服务器上读数据,把需要的数据在进入路由之前读取到,带着数据进入路由并显示(例如插值表达式的值)
使用resolve守卫也可以向路由传递数据
模拟案例:在进入商品信息的路由之前先读取商品信息,读好之后,带着信息进入路由
第一步:创建守卫
@Injectable()
export class ProductRsolve implements Resolve<Product> {
//Product 声明的泛型,resolve要解析出来的数据类型
constructor(
private router: Router
) { }
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
let productId = route.params['id']; // 拿到传进来的商品Id
if (productId == 1) {
return new Product(1, '电风扇');
} else {
this.router.navigate(['/home']);
return undefined;
}
}
}
要加@Injectable()装饰器<font siz='2">component不用加是因为自身已经集成了
当进入商品的路由时,商品id=1的时候,返回一个:Id是1,详情是电风扇的对象,
如果不是1的话就路由到home组件路由上
*在product.ts中创建Product类
// Product类
export class Product {
constructor(
public id: number,
public name: string
) { }
}
第二步:添加到路由配置中
const routes: Routes = [
{
path: 'product/:id', component: ProductComponent,
children: [
{ path: '', component: ProductDescComponent },
{ path: 'seller/:id', component: SellerInfoComponent }
],
resolve: { product: ProductRsolve }
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers:[ProductRsolve]
})
这里的resolve是一个对象,参数的名字就是想传入的参数名称
product: ProductRsolve(product由ProductRsolve守卫来生成)
第三步:在页面上接收值
// product.ts
export class ProductComponent implements OnInit {
productId: number;
productName: string;
constructor(
private activatedRoute: ActivatedRoute
) { }
ngOnInit() {
this.activatedRoute.params.subscribe((params: Params) => this.productId = params["id"]);
this.activatedRoute.data.subscribe((data: { product: Product }) => { // 订阅传进来的数据
this.productId = data.product.id; //把传进来的id和name赋给本地变量
this.productName = data.product.name;
})
}
}
export class Product {
constructor(
public id: number,
public name: string
) { }
}
效果预览:
从home页链接到商品详情1的时候,id=1所以显示了商品id=1,name是电风扇。再链接到商品详情2的时候id=2,路由直接跳到了home组件上。
总结:在进入组件之前把组件所需要的的数据加载好,拿数据或者出错了就不在进入目标路由