Angular系列教程之路由守卫
.markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rgba(37, 41, 51, 1) }
.markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 { line-height: 1.5; margin-top: 35px; margin-bottom: 10px; padding-bottom: 5px }
.markdown-body h1 { font-size: 24px; line-height: 38px; margin-bottom: 5px }
.markdown-body h2 { font-size: 22px; line-height: 34px; padding-bottom: 12px; border-bottom: 1px solid rgba(236, 236, 236, 1) }
.markdown-body h3 { font-size: 20px; line-height: 28px }
.markdown-body h4 { font-size: 18px; line-height: 26px }
.markdown-body h5 { font-size: 17px; line-height: 24px }
.markdown-body h6 { font-size: 16px; line-height: 24px }
.markdown-body p { line-height: inherit; margin-top: 22px; margin-bottom: 22px }
.markdown-body img { max-width: 100% }
.markdown-body hr { border-top: 1px solid rgba(221, 221, 221, 1); border-right: none; border-bottom: none; border-left: none; margin-top: 32px; margin-bottom: 32px }
.markdown-body code { border-radius: 2px; overflow-x: auto; background-color: rgba(255, 245, 245, 1); color: rgba(255, 80, 44, 1); font-size: 0.87em; padding: 0.065em 0.4em }
.markdown-body code, .markdown-body pre { font-family: Menlo, Monaco, Consolas, Courier New, monospace }
.markdown-body pre { overflow: auto; position: relative; line-height: 1.75 }
.markdown-body pre>code { font-size: 12px; padding: 15px 12px; margin: 0; word-break: normal; display: block; overflow-x: auto; color: rgba(51, 51, 51, 1); background: rgba(248, 248, 248, 1) }
.markdown-body a { text-decoration: none; color: rgba(2, 105, 200, 1); border-bottom: 1px solid rgba(209, 233, 255, 1) }
.markdown-body a:active, .markdown-body a:hover { color: rgba(39, 91, 140, 1) }
.markdown-body table { display: inline-block !important; font-size: 12px; width: auto; max-width: 100%; overflow: auto; border: 1px solid rgba(246, 246, 246, 1) }
.markdown-body thead { background: rgba(246, 246, 246, 1); color: rgba(0, 0, 0, 1); text-align: left }
.markdown-body tr:nth-child(2n) { background-color: rgba(252, 252, 252, 1) }
.markdown-body td, .markdown-body th { padding: 12px 7px; line-height: 24px }
.markdown-body td { min-width: 120px }
.markdown-body blockquote { color: rgba(102, 102, 102, 1); padding: 1px 23px; margin: 22px 0; border-left: 4px solid rgba(203, 203, 203, 1); background-color: rgba(248, 248, 248, 1) }
.markdown-body blockquote:after { display: block; content: "" }
.markdown-body blockquote>p { margin: 10px 0 }
.markdown-body ol, .markdown-body ul { padding-left: 28px }
.markdown-body ol li, .markdown-body ul li { margin-bottom: 0; list-style: inherit }
.markdown-body ol li .task-list-item, .markdown-body ul li .task-list-item { list-style: none }
.markdown-body ol li .task-list-item ol, .markdown-body ol li .task-list-item ul, .markdown-body ul li .task-list-item ol, .markdown-body ul li .task-list-item ul { margin-top: 0 }
.markdown-body ol ol, .markdown-body ol ul, .markdown-body ul ol, .markdown-body ul ul { margin-top: 3px }
.markdown-body ol li { padding-left: 6px }
.markdown-body .contains-task-list { padding-left: 0 }
.markdown-body .task-list-item { list-style: none }
@media (max-width: 720px) { .markdown-body h1 { font-size: 24px } .markdown-body h2 { font-size: 20px } .markdown-body h3 { font-size: 18px } }.markdown-body pre, .markdown-body pre>code.hljs { color: rgba(51, 51, 51, 1); background: rgba(248, 248, 248, 1) }
.hljs-comment, .hljs-quote { color: rgba(153, 153, 136, 1); font-style: italic }
.hljs-keyword, .hljs-selector-tag, .hljs-subst { color: rgba(51, 51, 51, 1); font-weight: 700 }
.hljs-literal, .hljs-number, .hljs-tag .hljs-attr, .hljs-template-variable, .hljs-variable { color: rgba(0, 128, 128, 1) }
.hljs-doctag, .hljs-string { color: rgba(221, 17, 68, 1) }
.hljs-section, .hljs-selector-id, .hljs-title { color: rgba(153, 0, 0, 1); font-weight: 700 }
.hljs-subst { font-weight: 400 }
.hljs-class .hljs-title, .hljs-type { color: rgba(68, 85, 136, 1); font-weight: 700 }
.hljs-attribute, .hljs-name, .hljs-tag { color: rgba(0, 0, 128, 1); font-weight: 400 }
.hljs-link, .hljs-regexp { color: rgba(0, 153, 38, 1) }
.hljs-bullet, .hljs-symbol { color: rgba(153, 0, 115, 1) }
.hljs-built_in, .hljs-builtin-name { color: rgba(0, 134, 179, 1) }
.hljs-meta { color: rgba(153, 153, 153, 1); font-weight: 700 }
.hljs-deletion { background: rgba(255, 221, 221, 1) }
.hljs-addition { background: rgba(221, 255, 221, 1) }
.hljs-emphasis { font-style: italic }
.hljs-strong { font-weight: 700 }
@[toc]
前言
在Angular中,路由守卫是一个非常有用的功能,可以帮助我们控制用户在导航过程中的权限和访问限制。通过使用路由守卫,我们可以拦截导航并根据需求决定是否允许用户继续访问特定的页面或组件。
路由守卫的类型
Angular提供了以下几种类型的路由守卫:
CanLoad:进入到当前路由的时候触发(若用户没有权限访问,相应的模块并不会被加载。这里是指对应组件的代码)。
CanActivate:用于控制是否允许用户访问目标路由。
CanActivateChild:用于控制是否允许用户访问目标路由的子路由。
CanDeactivate:用于控制是否允许用户离开当前路由。
Resolve:用于在路由激活之前获取必要的数据。
下面我们将逐个介绍这些路由守卫,并给出相应的示例代码。
CanLoad
进入到当前路由的时候触发(若用户没有权限访问,相应的模块并不会被加载。这里是指对应组件的代码)。
下面是一个示例代码,展示如何使用CanLoad守卫来控制访问权限:
import { Injectable } from '@angular/core';
import { CanLoad, Route, Router, UrlSegment } from '@angular/router';
@Injectable()
export class CanLoadGuard implements CanLoad {
constructor(private router: Router) { }
canLoad(
route: Route,
segments: UrlSegment[]
) {
// 在这里编写你的权限控制逻辑
const isAuthenticated = // 检查用户是否已登录
if (isAuthenticated) {
return true; // 允许导航
} else {
// 将用户重定向到登录页面
this.router.navigate(['/login']);
return false; // 拒绝导航
}
}
}
要使用CanLoad守卫,我们需要将它添加到路由配置中的目标路由上,如下所示:
const routes: Routes = [
{
path: 'dashboard',
component: DashboardComponent,
canLoad: [CanLoadGuard]
},
// 其他路由配置...
];
CanActivate
CanActivate守卫用于控制是否允许用户访问目标路由。当导航发生时,CanActivate守卫将被触发,并根据返回的布尔值来允许或拒绝导航。
下面是一个示例代码,展示如何使用CanActivate守卫来控制访问权限:
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private router: Router) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
// 在这里编写你的权限控制逻辑
const isAuthenticated = // 检查用户是否已登录
if (isAuthenticated) {
return true; // 允许导航
} else {
// 将用户重定向到登录页面
this.router.navigate(['/login']);
return false; // 拒绝导航
}
}
}
在上面的代码中,我们创建了一个名为AuthGuard的服务,并实现了CanActivate接口。在canActivate方法中,我们可以编写自己的权限控制逻辑。如果用户已经登录,我们返回true以允许导航,否则我们将用户重定向到登录页面并返回false拒绝导航。
要使用CanActivate守卫,我们需要将它添加到路由配置中的目标路由上,如下所示:
const routes: Routes = [
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [AuthGuard]
},
// 其他路由配置...
];
CanActivateChild
CanActivateChild守卫用于控制是否允许用户访问目标路由的子路由。它与CanActivate守卫的使用方式类似。
下面是一个示例代码,展示如何使用CanActivateChild守卫来控制访问权限:
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivateChild {
constructor(private router: Router) {}
canActivateChild(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
// 在这里编写你的权限控制逻辑
const isAuthenticated = // 检查用户是否已登录
if (isAuthenticated) {
return true; // 允许导航
} else {
// 将用户重定向到登录页面
this.router.navigate(['/login']);
return false; // 拒绝导航
}
}
}
要使用CanActivateChild守卫,我们需要将它添加到路由配置中的目标路由上,如下所示:
const routes: Routes = [
{
path: 'admin',
component: AdminComponent,
canActivateChild: [AuthGuard],
children: [
// 子路由配置...
]
},
// 其他路由配置...
];
CanDeactivate
CanDeactivate守卫用于控制是否允许用户离开当前路由。当用户尝试离开当前路由时,CanDeactivate守卫将被触发,并根据返回的布尔值来允许或拒绝离开。
下面是一个示例代码,展示如何使用CanDeactivate守卫来控制离开权限:
import { Injectable } from '@angular/core';
import { CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DirtyCheckGuard implements CanDeactivate<any> {
canDeactivate(
component: any,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot,
nextState?: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
// 在这里编写你的离开权限控制逻辑
const isDirty = // 检查当前组件是否有未保存的更改
if (isDirty) {
return confirm('您有未保存的更改,确定要离开吗?'); // 提示用户是否继续离开
} else {
return true; // 允许离开
}
}
}
在上面的代码中,我们创建了一个名为DirtyCheckGuard的服务,并实现了CanDeactivate接口。在canDeactivate方法中,我们可以编写自己的离开权限控制逻辑。如果当前组件有未保存的更改,我们将提示用户是否继续离开。
要使用CanDeactivate守卫,我们需要将它添加到路由配置中的目标路由上,如下所示:
const routes: Routes = [
{
path: 'profile',
component: ProfileComponent,
canDeactivate: [DirtyCheckGuard]
},
// 其他路由配置...
];
Resolve
Resolve守卫用于在路由激活之前获取必要的数据。它可以帮助我们在加载组件之前获取所需的数据,以便在组件内部使用。
下面是一个示例代码,展示如何使用Resolve守卫来获取数据:
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { DataService } from './data.service';
@Injectable({
providedIn: 'root'
})
export class DataResolver implements Resolve<any> {
constructor(private dataService: DataService) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<any> | Promise<any> | any {
// 在这里编写你获取数据的逻辑
return this.dataService.getData();
}
}
在上面的代码中,我们创建了一个名为DataResolver的服务,并实现了Resolve接口。在resolve方法中,我们可以编写自己的获取数据逻辑。在本例中,我们使用DataService服务来获取数据。
要使用Resolve守卫,我们需要将它添加到路由配置中的目标路由上,如下所示:
const routes: Routes = [
{
path: 'data',
component: DataComponent,
resolve: {
data: DataResolver
}
},
// 其他路由配置...
];
在上述代码中,我们将DataResolver添加到resolve属性中。这将确保在加载DataComponent之前先获取数据。
总结
路由守卫是Angular中一个非常有用的功能,可以帮助我们控制用户在导航过程中的权限和访问限制。通过使用CanLoad、CanActivate、CanActivateChild、CanDeactivate和Resolve守卫,我们可以实现各种导航控制需求,并为用户提供更好的体验。
示例代码仅为演示目的,你可以根据自己的需求进行修改和扩展。希望本文能够帮助你理解和使用Angular的路由守卫功能!
Angular系列教程之路由守卫的更多相关文章
- Fastify 系列教程一(路由和日志)
介绍 Fastify是一个高度专注于以最少开销和强大的插件架构,为开发人员提供最佳体验的Web框架. 它受到了 Hapi 和 Express 的启发,是目前最快的 Node 框架之一. Fastify ...
- Fastify 系列教程一 (路由和日志)
Fastify 系列教程: Fastify 系列教程一 (路由和日志) Fastify 系列教程二 (中间件.钩子函数和装饰器) Fastify 系列教程三 (验证.序列化和生命周期) Fastify ...
- Angular 从入坑到挖坑 - 路由守卫连连看
一.Overview Angular 入坑记录的笔记第六篇,介绍 Angular 路由模块中关于路由守卫的相关知识点,了解常用到的路由守卫接口,知道如何通过实现路由守卫接口来实现特定的功能需求,以及实 ...
- Fastify 系列教程二 (中间件、钩子函数和装饰器)
Fastify 系列教程: Fastify 系列教程一 (路由和日志) Fastify 系列教程二 (中间件.钩子函数和装饰器) 中间件 Fastify 提供了与 Express 和 Restify ...
- Fastify 系列教程三 (验证、序列化和生命周期)
Fastify 系列教程: Fastify 系列教程一 (路由和日志) Fastify 系列教程二 (中间件.钩子函数和装饰器) Fastify 系列教程三 (验证.序列化和生命周期) 验证 Fast ...
- Fastify 系列教程四 (求对象、响应对象和插件)
Fastify 系列教程: Fastify 系列教程一 (路由和日志) Fastify 系列教程二 (中间件.钩子函数和装饰器) Fastify 系列教程三 (验证.序列化和生命周期) Fastify ...
- Angular5 路由守卫
今年下半年一直很忙,没有多少时间来写博客,很多笔记都记在了本地一起提交到了git上边. 夏末的时候做的两个vue项目中有接触到vue的路由守卫,今天在另外一个angular上,发现路由守卫有异常,导致 ...
- Fastify 系列教程二 (中间件、钩子函数和装饰器)
Fastify 系列教程: Fastify 系列教程一 (路由和日志) Fastify 系列教程二 (中间件.钩子函数和装饰器) Fastify 系列教程三 (验证.序列化和生命周期) Fastify ...
- Angular入门到精通系列教程(13)- 路由守卫(Route Guards)
1. 摘要 2. 路由守卫(Route Guards) 2.1. 创建路由守卫 2.2. 控制路由是否可以激活 2.3. 控制路由是否退出(离开) 3. 总结 环境: Angular CLI: 11. ...
- Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数
上一篇:Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数 之前介绍了简单的路由以及传参,这篇文章我们将要学习复杂一些的路由以及传递其他附加参数.一个好的路由系统可以使我们 ...
随机推荐
- 华企盾DSC防泄密软件造成VS启动报目录错误
解决方法:找到安装路径下的Privateregistry.bin文件解密即可
- 使用容器快速在阿里云 ECS 多节点上搭建 Citus 12.1 集群
阿里云 ECS 机器节点 这里我们使用两台同一区域的 ECS 机器. 机器配置:2 核 2 G.(ps: 阿里云 99 元一年的活动) 一台安装 coordinator(协调器),这里内网 IP 为 ...
- java通过url得到文件对象(支持http和https)
文字标题:java通过url得到文件对象(支持http和https) 作者:锅巴 1.场景:通过一个url地址来得到一个文件,此方式就是通过一个url将文件下载到本地的临时文件,直接上代码 /** * ...
- Android SDK Manager 报错“加载 SDK 组件信息失败”。(Android SDK Manager complains with "Loading SDK component information failed."
[解决方案]: 将存储库设置更改为 Google .因此,在 android SDK 管理器上点击齿轮图标(设置),然后点击 Repository -> Google.
- Pdfium.Net.Free 一个免费的Pdfium的 .net包装器--概述
PdfiumViewer 是一个伟大的项目,可惜仓库现已经归档,This repository has been archived by the owner on Aug 2, 2019. It is ...
- Pikachu漏洞靶场 RCE(远程命令执行/代码执行)
RCE 文章目录 RCE 概述 exec "ping" exec "eval" 概述 RCE(remote command/code execute),远程命令 ...
- 案例分享-Exception.getMessage突然为null
背景 之前做的小工具一个jsqlparse+git做的小工具帮我节省时间摸鱼昨天突然停止工作,看了下jvm并没有退出,但是看日志确实有不少Error输出,虽说是一个普通的NPE,但是分析了一下却疑点重 ...
- android学习笔记(1)
Android 开发框架 android系统是一个开放且体积庞大的系统,从功能上,将android开发分为移植开发移动电话系统,android应用开发和android系统开发三种. 移动移植移动电话系 ...
- electron入门之试调工具remote(三)
electron入门到入土,从渲染线程中创建新窗口.2022-03-21入门版本17.1.2 electron重要概念,只有一个主线程,其他都是渲染进程或者叫子线程,他们不能直接相互操作,可以通过ip ...
- MyBatis入门操作
MyBatis入门操作,其实是我只想验证一下instanceof是否能在xml中使用 根据官网,下面我创建一个普通Maven项目,引入依赖: <dependency> <groupI ...