gpt4 book ai didi

Angular RouteGuard/动态导航

转载 作者:太空狗 更新时间:2023-10-29 19:32:35 24 4
gpt4 key购买 nike

我有一个应用程序,我的导航栏根据他们所在产品的“区域”而变化。我正在使用 Angulars Route Guards 来确保检查他们的访问权限,以便他们只能点击他们有权访问的路线.这很好用!

在我的 app-routing-module.ts 中,我(尝试)变得聪明并利用 ActivatedRouteSnapshot 获取所有子链接,然后为其构建导航。我想做的,也是使用 Route Guard 来决定是否应该显示子链接。

//守卫

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { environment } from '../../environments/environment';
import { MeService } from '../shared/services/me.service';

@Injectable()
export class AdminGuard implements CanActivate {
constructor(private _meService: MeService) {}
async canActivate(
next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
const user = await this._meService.getCurrentUser();
if (user && user.isUserAdminForCompany) {
return true;
} else {
return false;
}
}
}

//路线

export const routes: Routes = [
{ path: '', redirectTo: 'route1', pathMatch: 'full' },
{ path: 'route1', component: MyComponent,
children: [
{ path: '', redirectTo: 'overview', pathMatch: 'full' },
{ path: 'overview', component: Overview },
{ path: 'specs', component: Specs, canActivate: [ AdminGuard ] }
]
}
];

因此,一旦有人点击 MyComponent,我就会获取子路由并从中创建一个导航栏。如果 AdminGuard 返回,是否可以有某种指令或某种类型来利用 /spec 路径上的 AdminGuard 隐藏 URL错误的?由于我的一些/更多守卫需要对服务器进行某种异步调用或某些其他服务依赖项,所以我不能简单地在 *ngIf 中调用 guard.canActivate什么的。

我很确定它不存在,但似乎需要这样的设置:

<a [routerLink]="child.path" [canActivate]="child.guards">{{child.name}}</a>

更新我最终只是在 angular repo 上打开了一个 GitHub Feature Request。此功能似乎不存在(以开箱即用的方式)。在找到更好的解决方案之前,我将制作一个自定义指令,该指令将运行 Guards 中的逻辑以评估是否应公开某些内容。

https://github.com/angular/angular/issues/25342

最佳答案

这是我最终选择的。由于没有任何“开箱即用”的方式来利用守卫来完成我想做的事情,我只是制作了一个自定义指令。

关于此解决方案,我要注意的一件事是我讨厌以下两件事(我最终会改变)。

  1. 如果您的 Guards 有任何重定向功能,您必须对其进行更改,以便 Guards 仅返回 true/false。如果它在 Guard 失败时重定向页面,那么该指令将最终重定向你而不是仅仅隐藏元素

  2. this._elementRef.nativeElement.style.display = hasAccess ? 'block' : 'none'; 有比简单隐藏更好的解决方案。它应该像 *ngIf 一样,它甚至根本不渲染元素,除非它的计算结果为真。

实现:

<div appGuard [guards]="myGuardsArray">Something you want to hide .... </div>

指令:

import { Directive, ElementRef, Injector, Input, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';

@Directive({
selector: '[appGuard]'
})
export class GuardDirective implements OnInit {
@Input() guards: any[];
private readonly _elementRef: ElementRef;
private readonly _activatedRoute: ActivatedRoute;
private readonly _router: Router;
private readonly _injector: Injector;
constructor(_elementRef: ElementRef, _activatedRoute: ActivatedRoute, _router: Router,
_injector: Injector) {
this._elementRef = _elementRef;
this._activatedRoute = _activatedRoute;
this._router = _router;
this._injector = _injector;
}
async ngOnInit(): Promise<void> {
const canActivateInstances = this.guards.map( g => this._injector.get(g));
const results = await Promise.all(canActivateInstances.map( ca => ca.canActivate(this._activatedRoute.snapshot, this._router.routerState.snapshot)));
const hasAccess = results.find( r => !r) === false ? false : true;
this._elementRef.nativeElement.style.display = hasAccess ? 'block' : 'none';
}
}

更新

确定如何处理重定向的简单解决方案:

async canActivate(
next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
const user = await this._meService.getCurrentUser();
const result = user && user.isUserAdminForCompany;
if (next.routeConfig && next.routeConfig.canActivate.find( r => r.name === 'NameOfGuard') && !result) {
window.location.href = `${environment.webRoot}/sign-in`;
}
return result;
}

关于Angular RouteGuard/动态导航,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51716383/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com