18720358503 在线客服 人才招聘 返回顶部
企业动态 技术分享 行业动态

为何小程序流程裂变_Angular8路由守卫原理和使用

2021-01-08分享 "> 对不起,没有下一图集了!">
Angular8路由守卫原理和使用方法       这篇文章主要给大家介绍了关于Angular8路由守卫原理和使用方法的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Angular8具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

守卫,顾名思义,必须满足一定的条件得到许可方可通行,否则拒绝访问或者重定向。Angular中路由守卫可以借此处理一些权限问题,通常应用中存储了用户登录和用户权限信息,遇到路由导航时会进行验证是否可以跳转。

4种守卫类型

按照触发顺序依次为:canload(加载)、canActivate(进入)、canActivateChild(进入子路由)和canDeactivate(离开)。

一个所有守卫都是通过的守卫类:

import { Injectable } from '@angular/core';
import {
 CanActivate,
 Router,
 ActivatedRouteSna凡科抠图hot,
 RouterStateSna凡科抠图hot,
 CanActivateChild,
 CanLoad,
 CanDeactivate
} from '@angular/router';
import { Route } from 'piler/src/core';
import { NewsComponent } from '../component/ponent';

@Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate, CanActivateChild, CanLoad, CanDeactivate any { constructor( private router: Router canActivate(route: ActivatedRouteSna凡科抠图hot, state: RouterStateSna凡科抠图hot): boolean { // 权限控制逻辑如 是否登录/拥有访问权限 console.log('canActivate'); return true; canDeactivate( component: NewsComponent, currentRoute: ActivatedRouteSna凡科抠图hot, currentState: RouterStateSna凡科抠图hot, nextState: RouterStateSna凡科抠图hot) { console.log('canDeactivate'); return true; canActivateChild() { // 返回false则导航将失败/取消 // 也可以写入具体的业务逻辑 console.log('canActivateChild'); return true; canLoad(route: Route) { // 是否可以加载路由 console.log('canload'); return true; }

app-routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ErrorComponent } from './ponent';
import { AuthGuard } from './core/auth-guard';
const routes: Routes = [
 // 一般情况很少需要同时写多个守卫,如果有也是分开几个文件(针对复杂场景,否则一般使用canActivated足够)
 path: '',
 canLoad: [AuthGuard],
 canActivate: [AuthGuard],
 canActivateChild: [
 AuthGuard
 canDeactivate: [AuthGuard],
 loadChildren: () = import('./pages/pages.module').then(m = m.PagesModule)
 path: 'error',
 component: ErrorComponent,
 data: {
 title: '参数错误或者地址不存在'
 path: '**',
 redirectTo: 'error',
 pathMatch: 'full'
@NgModule({
 imports: [RouterModule.forRoot(routes)],
 exports: [RouterModule]
export class AppRoutingModule { }

使用场景分析

1.canLoad

默认值为true,表明路由是否可以被加载,一般不会认为控制这个守卫逻辑,99.99%情况下,默认所有app模块下路由均允许canLoad

2.canActivate

是否允许进入该路由,此场景多为权限限制的情况下,比如客户未登录的情况下查询某些资料页面,在此方法中去判断客户是否登陆,如未登录则强制导航到登陆页或者提示无权限,即将返回等信息提示。

3.canActivateChild

是否可以导航子路由,同一个路由不会同时设置canActivate为true,canActivateChild为false的情况,此外,这个使用场景很苛刻,尤其是懒加载路由模式下,暂时未使用到设置为false的场景。

4.CanDeactivate

路由离开的时候进行触发的守卫,使用场景比较经典,通常是某些页面比如表单页面填写的内容需要保存,客户突然跳转其它页面或者浏览器点击后退等改变地址的操作,可以在守卫中增加弹窗提示用户正在试图离开当前页面,数据还未保存 等提示。

场景模拟

登录判断

前期准备:login组件;配置login路由
<应该只会剩余一个路由导航

 !-- NG-ZORRO -- 
 router-outlet /router-outlet 
<页面中要加入header和footer部分变为如下:

 app-header /app-header 
 div nz-row 
 div nz-col nzSpan="24" 
 router-outlet /router-outlet 
 /div 
 /div 
 app-footer /app-footer 

app-routing.module.ts 中路由配置2种模式分析:

// 非懒加载模式
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ErrorComponent } from './ponent';
import { AuthGuard } from './core/auth-guard';
import { LoginComponent } from './component/ponent';
import { PagesComponent } from './ponent';
import { IndexComponent } from './component/ponent';
const routes: Routes = [
 // 一般情况很少需要同时写多个守卫,如果有也是分开几个文件(针对复杂场景,否则一般使用canActivated足够)
 path: '',
 canLoad: [AuthGuard],
 canActivate: [AuthGuard],
 canActivateChild: [
 AuthGuard
 canDeactivate: [AuthGuard],
 component: PagesComponent,
 children: [
 path: 'index',
 component: IndexComponent
 // ...
 // loadChildren: () = import('./pages/pages.module').then(m = m.PagesModule)
 path: 'login',
 component: LoginComponent,
 data: {
 title: '登录'
 path: 'error',
 component: ErrorComponent,
 data: {
 title: '参数错误或者地址不存在'
 path: '**',
 redirectTo: 'error',
 pathMatch: 'full'
@NgModule({
 imports: [RouterModule.forRoot(routes)],
 exports: [RouterModule]
export class AppRoutingModule { }

非懒加载模式下,想要pages组件能够正常显示切换的路由和固定头部足部,路由只能像上述这样配置,也就是所有组件都在app模块中声明,显然不是很推荐这种模式,切换回懒加载模式:

 path: '',
 canLoad: [AuthGuard],
 canActivate: [AuthGuard],
 canActivateChild: [
 AuthGuard
 canDeactivate: [AuthGuard],
 loadChildren: () = import('./pages/pages.module').then(m = m.PagesModule)
 },

pages-routing.module.ts

初始模板:

const routes: Routes = [
 path: '',
 redirectTo: 'index',
 pathMatch: 'full'
 path: 'index',
 component: IndexComponent,
 data: {
 title: '公司'
 path: 'about',
 component: AboutComponent,
 data: {
 title: '关于我们'
 path: 'contact',
 component: ContactComponent,
 data: {
 title: '联系我们'
 path: 'news',
 canDeactivate: [AuthGuard],
 loadChildren: () = import('../component/news/news.module').then(m = m.NewsModule)
]

浏览器截图:

明明我们的html写了头部和底部组件却没显示?
<中有个 app-root /app-root ,这就表明app组件被直接插入了dom中,反观pages组件,根本不存在直接插进dom的情况,所以这个组件根本没被加载,验证我们的猜想很简单:

export class PagesComponent implements OnInit {
 constructor() { }
 ngOnInit() {
 alert();
}
<效果,所以路由配置要参照更改:

const routes: Routes = [
 path: '',
 component: PagesComponent,
 children: [
 path: '',
 redirectTo: 'index',
 pathMatch: 'full'
 path: 'index',
 component: IndexComponent,
 data: {
 title: '公司'
 path: 'about',
 component: AboutComponent,
 data: {
 title: '关于我们'
 path: 'contact',
 component: ContactComponent,
 data: {
 title: '联系我们'
 path: 'news',
 canDeactivate: [AuthGuard],
 loadChildren: () = import('../component/news/news.module').then(m = m.NewsModule)
];

这样写,pages组件就被加载了,重回正题,差点回不来,我们在登录组件中写了简单的登录逻辑:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms';
import { Router } from '@angular/router';
@Component({
 selector: 'app-login',
 ',
 styleUrls: ['./ponent.scss']
export class LoginComponent implements OnInit {
 loginForm: FormGroup;
 constructor(
 private fb: FormBuilder,
 private router: Router
 ) { }
 ngOnInit() {
 this.loginForm = this.fb.group({
 loginName: ['', [Validators.required]],
 password: ['', [Validators.required]]
 console.log(this.loginForm);
 loginSubmit(event, value) {
 if (this.loginForm.valid) {
 window.localStorage.setItem('loginfo', JSON.stringify(this.loginForm.value));
 this.router.navigateByUrl('index');
}

守卫中:

canActivate(route: ActivatedRouteSna凡科抠图hot, state: RouterStateSna凡科抠图hot): boolean {
 // 权限控制逻辑如 是否登录/拥有访问权限
 console.log('canActivate', route);
 const isLogin = window.localStorage.getItem('loginfo') true : false;
 if (!isLogin) {
 console.log('login');
 this.router.navigateByUrl('login');
 return true;
 }

路由离开(选定应用的组件是contact组件):

canDeactivate(
 component: ContactComponent,
 currentRoute: ActivatedRouteSna凡科抠图hot,
 currentState: RouterStateSna凡科抠图hot,
 nextState: RouterStateSna凡科抠图hot): Observable boolean | Promise boolean | boolean {
 console.log('canDeactivate');
 ponent.pageLeave();
 }

默认数据状态时未保存,可以选择不保存直接跳转也可以保存之后再跳转。

此场景多用于复杂表单页或者一些填写资料步骤的过程中,甚至浏览器后退和前进的操作也会触发这个守卫,唯一不足的地方时这个守卫绑定的是单一页面,无法统一对多个页面进行拦截。

"> 对不起,没有下一图集了!">
在线咨询