Angular路由——路由守卫
一、路由守卫
当用户满足一定条件才被允许进入或者离开一个路由。
路由守卫场景:
只有当用户登录并拥有某些权限的时候才能进入某些路由。
一个由多个表单组成的向导,例如注册流程,用户只有在当前路由的组件中填写了满足要求的信息才可以导航到下一个路由。
当用户未执行保存操作而试图离开当前导航时提醒用户。
Angular提供了一些钩子帮助控制进入或离开路由。这些钩子就是路由守卫,可以通过这些钩子实现上面场景。
- CanActivate: 处理导航到某路由的情况。
- CanDeactivate: 处理从当前路由离开的情况。
- Resolve: 在路由激活之前获取路由数据。
配置路由时候用到一些属性,path, component, outlet, children, 路由守卫也是路由属性。
二、CanActivate
实例:只让登录用户进入产品信息路由。
新建guard目录。目录下新建login.guard.ts。
LoginGuard类实现CanActivate接口,返回true或false,Angular根据返回值判断请求通过或不通过。
import { CanActivate } from "@angular/router"; export class LoginGuard implements CanActivate{
canActivate(){
let loggedIn :boolean= Math.random()<0.5;
if(!loggedIn){
console.log("用户未登录");
}
return loggedIn;
}
}
配置product路由。先把LoginGuard加入providers,在指定路由守卫。
canActivate可以指定多个守卫,值是一个数组。
const routes: Routes = [
{ path: '', redirectTo : 'home',pathMatch:'full' },
{ path: 'chat', component: ChatComponent, outlet: "aux"},//辅助路由
{ path: 'home', component: HomeComponent },
{ path: 'product/:id', component: ProductComponent, children:[
{ path: '', component : ProductDescComponent },
{ path: 'seller/:id', component : SellerInfoComponent }
] ,canActivate: [LoginGuard]},
{ path: '**', component: Code404Component }
];
效果:点商品详情链接控制台会提醒用户未登录,不能进入商品详情路由。
三、CanDeactivate
离开时候的路由守卫。提醒用户执行保存操作后才能离开。
在guard目录下新建一个unsave.guard.ts的文件。
CanDeactivate接口有一个范型,指定当前组件的类型。
CanDeactivate方法第一个参数就是接口指定的范型类型的组件,根据这个要保护的组件的状态,或者调用方法来决定用户是否能够离开。
import { CanDeactivate } from "@angular/router";
import { ProductComponent } from "../product/product.component"; export class UnsaveGuard implements CanDeactivate<ProductComponent>{
//第一个参数 范型类型的组件
//根据当前要保护组件 的状态 判断当前用户是否能够离开
canDeactivate(component: ProductComponent){
return window.confirm('你还没有保存,确定要离开吗?');
}
}
配置路由,同样先加到provider,再配置路由。
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { ProductComponent } from './product/product.component';
import { Code404Component } from './code404/code404.component';
import { ProductDescComponent } from './product-desc/product-desc.component';
import { SellerInfoComponent } from './seller-info/seller-info.component';
import { ChatComponent } from './chat/chat.component';
import { LoginGuard } from './guard/login.guard';
import { UnsaveGuard } from './guard/unsave.guard'; const routes: Routes = [
{ path: '', redirectTo : 'home',pathMatch:'full' },
{ path: 'chat', component: ChatComponent, outlet: "aux"},//辅助路由
{ path: 'home', component: HomeComponent },
{ path: 'product/:id', component: ProductComponent, children:[
{ path: '', component : ProductDescComponent },
{ path: 'seller/:id', component : SellerInfoComponent }
] ,canActivate: [LoginGuard],
canDeactivate: [UnsaveGuard]},
{ path: '**', component: Code404Component }
]; @NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [LoginGuard,UnsaveGuard]
})
export class AppRoutingModule { }
效果:
点ok离开当前页面,cancel留在当前页面。
四、Resolve守卫
http请求数据返回有延迟,导致模版无法立刻显示。
数据返回之前模版上所有需要用插值表达式显示某个controller的值的地方都是空的。用户体验不好。
resolve解决办法:在进入路由之前去服务器读数据,把需要的数据都读好以后,带着这些数据进到路由里,立刻就把数据显示出来。
实例:
在进入商品信息路由之前,准备好商品信息再进入路由。 拿不到信息,或者拿信息出问题了,直接跳到错误信息页面,或者弹出提示,就不再进入目标路由。
先在product.component.ts中声明商品信息类型。
export class Product{
constructor(public id:number, public name:string){
}
}
在guard目录下新建product.resolve.ts。ProductResolve类实现了Resolve接口。
Resolve也要声明一个范型,范型就是resolve要解析出来的数据的类型。
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from "@angular/router"; import { Injectable } from "@angular/core";
import { Observable } from "rxjs/Observable";
import { Product } from "../product/product.component"; @Injectable()
export class ProductResolve implements Resolve<Product>{ constructor(private router: Router) {
} resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any {
let productId: number = route.params["id"];
if (productId == 2) { //正确id
return new Product(1, "iPhone7");
} else { //id不是1导航回首页
this.router.navigate(["/home"]);
return undefined;
}
}
}
路由配置:Provider里声明,product路由里配置。
resolve是一个对象,对象里参数的名字就是想传入的参数的名字product,用ProductResolve来解析生成。
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { ProductComponent } from './product/product.component';
import { Code404Component } from './code404/code404.component';
import { ProductDescComponent } from './product-desc/product-desc.component';
import { SellerInfoComponent } from './seller-info/seller-info.component';
import { ChatComponent } from './chat/chat.component';
import { LoginGuard } from './guard/login.guard';
import { UnsaveGuard } from './guard/unsave.guard';
import { ProductResolve } from './guard/product.resolve'; const routes: Routes = [
{ path: '', redirectTo : 'home',pathMatch:'full' },
{ path: 'chat', component: ChatComponent, outlet: "aux"},//辅助路由
{ path: 'home', component: HomeComponent },
{ path: 'product/:id', component: ProductComponent, children:[
{ path: '', component : ProductDescComponent },
{ path: 'seller/:id', component : SellerInfoComponent }
] ,
// canActivate: [LoginGuard],
// canDeactivate: [UnsaveGuard],
resolve:{ //resolve是一个对象
product : ProductResolve //想传入product,product由ProductResolve生成
}},
{ path: '**', component: Code404Component }
]; @NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [LoginGuard,UnsaveGuard,ProductResolve]
})
export class AppRoutingModule { }
修改一下product.component.ts 和模版,显示商品id和name。
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router'; @Component({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit { private productId: number;
private productName: string;
constructor(private routeInfo: ActivatedRoute) { } ngOnInit() {
// this.routeInfo.params.subscribe((params: Params)=> this.productId=params["id"]);
this.routeInfo.data.subscribe(
(data:{product:Product})=>{
this.productId=data.product.id;
this.productName=data.product.name;
}
);
} } export class Product{
constructor(public id:number, public name:string){
}
}
<div class="product">
<p>
这里是商品信息组件
</p>
<p>
商品id是: {{productId}}
</p>
<p>
商品名称是: {{productName}}
</p> <a [routerLink]="['./']">商品描述</a>
<a [routerLink]="['./seller',99]">销售员信息</a>
<router-outlet></router-outlet>
</div>
效果:
点商品详情链接,传入商品ID为2,在resolve守卫中是正确id,会返回一条商品数据。
点商品详情按钮,传入商品ID是3,是错误id,会直接跳转到主页。
本文作者starof,因知识本身在变化,作者也在不断学习成长,文章内容也不定时更新,为避免误导读者,方便追根溯源,请诸位转载注明出处:http://www.cnblogs.com/starof/p/9012193.html 有问题欢迎与我讨论,共同进步。
Angular路由——路由守卫的更多相关文章
- Vue的钩子函数[路由导航守卫、keep-alive、生命周期钩子]
前言 说到Vue的钩子函数,可能很多人只停留在一些很简单常用的钩子(created,mounted),而且对于里面的区别,什么时候该用什么钩子,并没有仔细的去研究过,且Vue的生命周期在面试中也算是比 ...
- Angular 4 路由介绍
Angular 4 路由 1. 创建工程 ng new router --routing 2. 创建home和product组件 ng g component home ng g component ...
- angular -- ng-ui-route路由及其传递参数?script标签版
考虑到 多视图等因素,所以 angular 的路由考虑使用 ng-ui-route来做,而不使用 ng-route来做! <!DOCTYPE html> <html lang=&qu ...
- angular 之路由
1.用angular-cli建一个工程自带路由怎么做? 命令:ng new 项目名 --routing 2.怎么使用路由器和路由器的一些基本使用. //html页面 <a routerLink ...
- angular 前端路由不生效解决方案
angular 前端路由不生效解决方案 Intro 最近使用 Angular 为我的活动室预约项目开发一个前后端分离的客户端,在部署上遇到了一个问题,前端路由不生效,这里记录一下.本地开发正常,但是部 ...
- Angular配置路由以及动态路由取值传值跳转
Angular配置路由 1.找到 app-routing.module.ts 配置路由 引入组件 import { HomeComponent } from './home/home.componen ...
- vue之路由导航守卫-全局前置守卫
一.使用方式 全局前置守卫用于在路由配置生效之前进行一些动作,可以使用 router.beforeEach 注册一个全局前置守卫: const router = new VueRouter({ ... ...
- 【VUE】5.路由导航守卫
1. 功能需求 1. 当用户登陆成功后,把得到的token存到Session Storage 2. components -> Form.vue , 对预验证进行校验,如果验证不正确就跳出,如果 ...
- AngularJS路由系列(2)--刷新、查看路由,路由事件和URL格式,获取路由参数,路由的Resolve
本系列探寻AngularJS的路由机制,在WebStorm下开发.主要包括: ● 刷新路由● 查看当前路由以及所有路由● 路由触发事件● 获取路由参数 ● 路由的resolve属性● 路由URL格式 ...
随机推荐
- ROS_Kinetic_02 ROS Kinetic 迁移指南及中文wiki指南(Migration guide)
ROS_Kinetic_02 ROS Kinetic 迁移指南(Migration guide) 对于ROS Kinetic Kame有些功能包已经更新改变,提供关于这些包的迁移注意或教程.主要针对于 ...
- 通用数据水平层级选择控件v0.70升级版使其支持jQuery v1.9.1
升级原因:作者原来脚本支持的jquery版本太低了,查找了下资料,使得它能支持最新版本的jquery 备注说明:脚本代码源作者跟源文出处很难找,只能在此特感谢他的分享. 更新部分: 1.新版本不再支持 ...
- Jeff Atwood:Google的头号UI问题
谷歌在用户界面上追求的"极简主义"是让人叹为观止的.但是,他们首页上有个问题一直让我困惑不解.要知道,这个页面可是每天都被下载几百万次哦: 真有人在使用"I'm Feel ...
- 安装mysql到服务器的linux环境下
1·安装mysql 命令:yum -y install httpd php mysql mysql-server 2·配置mysql 配置开机启动服务 /sbin/chkconfig --add my ...
- 海量数据挖掘MMDS week2: Nearest-Neighbor Learning最近邻学习
http://blog.csdn.net/pipisorry/article/details/48894963 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...
- 简述Java内存泄露
翻译人员: 铁锚翻译时间: 2013年11月4日原文链接: The Introduction of Memory Leaks内存管理一直是Java 所鼓吹的强大优点.开发者只需要简单地创建对象,而Ja ...
- 【面试笔试算法】牛客网一站通Offer编程题2016.4.19
牛客网一站通offer (一)字符串变形 1. 题目: 对于一个给定的字符串,我们需要在线性(也就是O(n))的时间里对它做一些变形.首先这个字符串中包含着一些空格,就像"Hello Wor ...
- hadoop namenode格式化问题汇总
hadoop namenode格式化问题汇总 (持续更新) 0 Hadoop集群环境 3台rhel6.4,2个namenode+2个zkfc, 3个journalnode+zookeeper-serv ...
- android Google推荐的容器SparseArrayCompat简介
android Google推荐的容器SparseArrayCompat简介 private static SparseArrayCompat<BaseFragment> mCaches ...
- 【一天一道LeetCode】#11Container With Most Water
一天一道LeetCode系列 (一)题目 Given n non-negative integers a1, a2, -, an, where each represents a point at c ...