一、路由守卫

当用户满足一定条件才被允许进入或者离开一个路由。

路由守卫场景:

只有当用户登录并拥有某些权限的时候才能进入某些路由。

一个由多个表单组成的向导,例如注册流程,用户只有在当前路由的组件中填写了满足要求的信息才可以导航到下一个路由。

当用户未执行保存操作而试图离开当前导航时提醒用户。

Angular提供了一些钩子帮助控制进入或离开路由。这些钩子就是路由守卫,可以通过这些钩子实现上面场景。

  • CanActivate: 处理导航到某路由的情况。
  • CanDeactivate: 处理从当前路由离开的情况。
  • Resolve: 在路由激活之前获取路由数据。

配置路由时候用到一些属性,path, component, outlet, children, 路由守卫也是路由属性。

二、CanActivate

实例:只让登录用户进入产品信息路由。

新建guard目录。目录下新建login.guard.ts。

LoginGuard类实现CanActivate接口,返回true或false,Angular根据返回值判断请求通过或不通过。

  1. import { CanActivate } from "@angular/router";
  2.  
  3. export class LoginGuard implements CanActivate{
  4. canActivate(){
  5. let loggedIn :boolean= Math.random()<0.5;
  6. if(!loggedIn){
  7. console.log("用户未登录");
  8. }
  9. return loggedIn;
  10. }
  11. }

配置product路由。先把LoginGuard加入providers,在指定路由守卫。

canActivate可以指定多个守卫,值是一个数组。

  1. const routes: Routes = [
  2. { path: '', redirectTo : 'home',pathMatch:'full' },
  3. { path: 'chat', component: ChatComponent, outlet: "aux"},//辅助路由
  4. { path: 'home', component: HomeComponent },
  5. { path: 'product/:id', component: ProductComponent, children:[
  6. { path: '', component : ProductDescComponent },
  7. { path: 'seller/:id', component : SellerInfoComponent }
  8. ] ,canActivate: [LoginGuard]},
  9. { path: '**', component: Code404Component }
  10. ];

效果:点商品详情链接控制台会提醒用户未登录,不能进入商品详情路由。

三、CanDeactivate

离开时候的路由守卫。提醒用户执行保存操作后才能离开。

在guard目录下新建一个unsave.guard.ts的文件。

CanDeactivate接口有一个范型,指定当前组件的类型。

CanDeactivate方法第一个参数就是接口指定的范型类型的组件,根据这个要保护的组件的状态,或者调用方法来决定用户是否能够离开。

  1. import { CanDeactivate } from "@angular/router";
  2. import { ProductComponent } from "../product/product.component";
  3.  
  4. export class UnsaveGuard implements CanDeactivate<ProductComponent>{
  5. //第一个参数 范型类型的组件
  6. //根据当前要保护组件 的状态 判断当前用户是否能够离开
  7. canDeactivate(component: ProductComponent){
  8. return window.confirm('你还没有保存,确定要离开吗?');
  9. }
  10. }

配置路由,同样先加到provider,再配置路由。

  1. import { NgModule } from '@angular/core';
  2. import { Routes, RouterModule } from '@angular/router';
  3. import { HomeComponent } from './home/home.component';
  4. import { ProductComponent } from './product/product.component';
  5. import { Code404Component } from './code404/code404.component';
  6. import { ProductDescComponent } from './product-desc/product-desc.component';
  7. import { SellerInfoComponent } from './seller-info/seller-info.component';
  8. import { ChatComponent } from './chat/chat.component';
  9. import { LoginGuard } from './guard/login.guard';
  10. import { UnsaveGuard } from './guard/unsave.guard';
  11.  
  12. const routes: Routes = [
  13. { path: '', redirectTo : 'home',pathMatch:'full' },
  14. { path: 'chat', component: ChatComponent, outlet: "aux"},//辅助路由
  15. { path: 'home', component: HomeComponent },
  16. { path: 'product/:id', component: ProductComponent, children:[
  17. { path: '', component : ProductDescComponent },
  18. { path: 'seller/:id', component : SellerInfoComponent }
  19. ] ,canActivate: [LoginGuard],
  20. canDeactivate: [UnsaveGuard]},
  21. { path: '**', component: Code404Component }
  22. ];
  23.  
  24. @NgModule({
  25. imports: [RouterModule.forRoot(routes)],
  26. exports: [RouterModule],
  27. providers: [LoginGuard,UnsaveGuard]
  28. })
  29. export class AppRoutingModule { }

效果:

点ok离开当前页面,cancel留在当前页面。

四、Resolve守卫

http请求数据返回有延迟,导致模版无法立刻显示。

数据返回之前模版上所有需要用插值表达式显示某个controller的值的地方都是空的。用户体验不好。

resolve解决办法:在进入路由之前去服务器读数据,把需要的数据都读好以后,带着这些数据进到路由里,立刻就把数据显示出来。

实例:

在进入商品信息路由之前,准备好商品信息再进入路由。 拿不到信息,或者拿信息出问题了,直接跳到错误信息页面,或者弹出提示,就不再进入目标路由。

先在product.component.ts中声明商品信息类型。

  1. export class Product{
  2. constructor(public id:number, public name:string){
  3. }
  4. }

在guard目录下新建product.resolve.ts。ProductResolve类实现了Resolve接口。

Resolve也要声明一个范型,范型就是resolve要解析出来的数据的类型。

  1. import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from "@angular/router";
  2.  
  3. import { Injectable } from "@angular/core";
  4. import { Observable } from "rxjs/Observable";
  5. import { Product } from "../product/product.component";
  6.  
  7. @Injectable()
  8. export class ProductResolve implements Resolve<Product>{
  9.  
  10. constructor(private router: Router) {
  11. }
  12.  
  13. resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any {
  14. let productId: number = route.params["id"];
  15. if (productId == 2) { //正确id
  16. return new Product(1, "iPhone7");
  17. } else { //id不是1导航回首页
  18. this.router.navigate(["/home"]);
  19. return undefined;
  20. }
  21. }
  22. }

路由配置:Provider里声明,product路由里配置。

resolve是一个对象,对象里参数的名字就是想传入的参数的名字product,用ProductResolve来解析生成。

  1. import { NgModule } from '@angular/core';
  2. import { Routes, RouterModule } from '@angular/router';
  3. import { HomeComponent } from './home/home.component';
  4. import { ProductComponent } from './product/product.component';
  5. import { Code404Component } from './code404/code404.component';
  6. import { ProductDescComponent } from './product-desc/product-desc.component';
  7. import { SellerInfoComponent } from './seller-info/seller-info.component';
  8. import { ChatComponent } from './chat/chat.component';
  9. import { LoginGuard } from './guard/login.guard';
  10. import { UnsaveGuard } from './guard/unsave.guard';
  11. import { ProductResolve } from './guard/product.resolve';
  12.  
  13. const routes: Routes = [
  14. { path: '', redirectTo : 'home',pathMatch:'full' },
  15. { path: 'chat', component: ChatComponent, outlet: "aux"},//辅助路由
  16. { path: 'home', component: HomeComponent },
  17. { path: 'product/:id', component: ProductComponent, children:[
  18. { path: '', component : ProductDescComponent },
  19. { path: 'seller/:id', component : SellerInfoComponent }
  20. ] ,
  21. // canActivate: [LoginGuard],
  22. // canDeactivate: [UnsaveGuard],
  23. resolve:{ //resolve是一个对象
  24. product : ProductResolve //想传入product,product由ProductResolve生成
  25. }},
  26. { path: '**', component: Code404Component }
  27. ];
  28.  
  29. @NgModule({
  30. imports: [RouterModule.forRoot(routes)],
  31. exports: [RouterModule],
  32. providers: [LoginGuard,UnsaveGuard,ProductResolve]
  33. })
  34. export class AppRoutingModule { }

修改一下product.component.ts 和模版,显示商品id和name。

  1. import { Component, OnInit } from '@angular/core';
  2. import { ActivatedRoute, Params } from '@angular/router';
  3.  
  4. @Component({
  5. selector: 'app-product',
  6. templateUrl: './product.component.html',
  7. styleUrls: ['./product.component.css']
  8. })
  9. export class ProductComponent implements OnInit {
  10.  
  11. private productId: number;
  12. private productName: string;
  13. constructor(private routeInfo: ActivatedRoute) { }
  14.  
  15. ngOnInit() {
  16. // this.routeInfo.params.subscribe((params: Params)=> this.productId=params["id"]);
  17. this.routeInfo.data.subscribe(
  18. (data:{product:Product})=>{
  19. this.productId=data.product.id;
  20. this.productName=data.product.name;
  21. }
  22. );
  23. }
  24.  
  25. }
  26.  
  27. export class Product{
  28. constructor(public id:number, public name:string){
  29. }
  30. }
  1. <div class="product">
  2. <p>
  3. 这里是商品信息组件
  4. </p>
  5. <p>
  6. 商品id是: {{productId}}
  7. </p>
  8. <p>
  9. 商品名称是: {{productName}}
  10. </p>
  11.  
  12. <a [routerLink]="['./']">商品描述</a>
  13. <a [routerLink]="['./seller',99]">销售员信息</a>
  14. <router-outlet></router-outlet>
  15. </div>

效果:

点商品详情链接,传入商品ID为2,在resolve守卫中是正确id,会返回一条商品数据。

点商品详情按钮,传入商品ID是3,是错误id,会直接跳转到主页。

本文作者starof,因知识本身在变化,作者也在不断学习成长,文章内容也不定时更新,为避免误导读者,方便追根溯源,请诸位转载注明出处:http://www.cnblogs.com/starof/p/9012193.html 有问题欢迎与我讨论,共同进步。

Angular路由——路由守卫的更多相关文章

  1. Vue的钩子函数[路由导航守卫、keep-alive、生命周期钩子]

    前言 说到Vue的钩子函数,可能很多人只停留在一些很简单常用的钩子(created,mounted),而且对于里面的区别,什么时候该用什么钩子,并没有仔细的去研究过,且Vue的生命周期在面试中也算是比 ...

  2. Angular 4 路由介绍

    Angular 4 路由 1. 创建工程 ng new router --routing 2. 创建home和product组件 ng g component home ng g component ...

  3. angular -- ng-ui-route路由及其传递参数?script标签版

    考虑到 多视图等因素,所以 angular 的路由考虑使用 ng-ui-route来做,而不使用 ng-route来做! <!DOCTYPE html> <html lang=&qu ...

  4. angular 之路由

    1.用angular-cli建一个工程自带路由怎么做? 命令:ng new  项目名 --routing 2.怎么使用路由器和路由器的一些基本使用. //html页面 <a routerLink ...

  5. angular 前端路由不生效解决方案

    angular 前端路由不生效解决方案 Intro 最近使用 Angular 为我的活动室预约项目开发一个前后端分离的客户端,在部署上遇到了一个问题,前端路由不生效,这里记录一下.本地开发正常,但是部 ...

  6. Angular配置路由以及动态路由取值传值跳转

    Angular配置路由 1.找到 app-routing.module.ts 配置路由 引入组件 import { HomeComponent } from './home/home.componen ...

  7. vue之路由导航守卫-全局前置守卫

    一.使用方式 全局前置守卫用于在路由配置生效之前进行一些动作,可以使用 router.beforeEach 注册一个全局前置守卫: const router = new VueRouter({ ... ...

  8. 【VUE】5.路由导航守卫

    1. 功能需求 1. 当用户登陆成功后,把得到的token存到Session Storage 2. components -> Form.vue , 对预验证进行校验,如果验证不正确就跳出,如果 ...

  9. AngularJS路由系列(2)--刷新、查看路由,路由事件和URL格式,获取路由参数,路由的Resolve

    本系列探寻AngularJS的路由机制,在WebStorm下开发.主要包括: ● 刷新路由● 查看当前路由以及所有路由● 路由触发事件● 获取路由参数 ● 路由的resolve属性● 路由URL格式 ...

随机推荐

  1. struts2 令牌 实现源代码 JSP

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"% ...

  2. OC利用ijkplayer框架按照步骤集成实现电视直播

    一. 下载ijkplayer ijkplayer下载地址:https://github.com/Bilibili/ijkplayer 下载完成后解压, 解压后文件夹内部目录如下图: ijkplayer ...

  3. Swift的基础之关于“!”和“?”的使用介绍

    swift编程,不外乎是定义属性或者函数(方法),访问属性或者调用函数,类型转换,?和!在这几个过程中,都有一展身手的时候,而且,每次要考虑使用的时候,它们俩都会一起出现在我们的大脑中,用还是不用,如 ...

  4. Leetcode_24_Swap Nodes in Pairs

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/43302355 Given a linked list, s ...

  5. android数据保存之greendao

    有时我们的数据属于保存到数据库,对于Android应用和IOS应用,我们一般都会使用SQLite这个嵌入式的数据库作为我们保存数据的工具.由于我们直接操作数据库比较麻烦,而且管理起来也非常的麻烦,以前 ...

  6. 原生CSS动画回调事件

    原文链接: Detecting CSS Animation Completion with JavaScript 原文日期: 2014年02月20日 翻译日期: 2014年02月21日 翻译人员: 铁 ...

  7. NDK 与 JNI 的关系

    简介 JNI是java语言提供的Java和C/C++相互沟通的机制,Java可以通过JNI调用本地的C/C++代码,本地的C/C++的代码也可以调用java代码.JNI 是本地编程接口,Java和C/ ...

  8. Workflow Notification Mailer Setup

    Workflow notification mailer setup in R12 is similar to 11i ( In both release 11i (OWF.H and higher ...

  9. 【Android 应用开发】Android UI 设计之 TextView EditText 组件属性方法最详细解析

    . 作者 :万境绝尘  转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/18964835 . TextView 相关类的继承结构 ...

  10. Java-Filter-FilterChain-FilterConfig源码

    public interface Filter { /** * Called by the web container to indicate to a filter that it is being ...