[英]How to router.navigate to same route in Angular 4 and catch the same event?
[英]Angular: how to call router.navigate() relative to target route in a RouteGuard?
我有一個使用 Angular 4 開發的現有項目。我需要根據用戶權限控制對特定路由的訪問。 簡化的路由配置如下所示:
[
{ path: '', redirectTo: '/myApp/home(secondary:xyz)', pathMatch: 'full' },
{ path: 'myApp'
children: [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', ... },
...
{ path: 'product'
children: [
{ path: '', redirectTo: 'categoryA', pathMatch: 'full' },
{ path: 'categoryA', component: CategoryAComponent, canActivate: [CategoryACanActivateGuard]},
{ path: 'categoryB', component: CategoryBComponent},
...
]
},
...
]
},
...
]
現在,我想控制對www.myWeb.com/myApp/product/categoryA
的訪問。 如果用戶沒有足夠的權限,他/她將被重定向到... /product/CategoryB
。 我寫了一個CanActivate
RouteGuard 來做到這一點,保護 class 看起來像這樣:
import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot, ActivatedRoute } from '@angular/router';
import { MyService } from '... my-service.service';
@Injectable()
export class CategoryACanActivateGuard implements CanActivate {
constructor(private myService: MyService, private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
return this.myService.checkPermission()
.then(result => {
if (!result.hasAccess) {
//redirect here
this.router.navigate(['./myApp/product/categoryB']);
//works, but I want to remove hardcoding 'myApp'
//this.router.navigate(['../../categoryB']);
//doesn't work, redirects to home page
//this.router.navigate(['./categoryB'], { relativeTo: this.route});
//do not have this.route object. Injecting Activated route in the constructor did not solve the problem
}
return result.hasAccess;
});
}
}
一切正常,但我希望相對於目標路由進行重定向,如下所示:
this.router.navigate(['/product/categoryB'], { relativeTo: <route-of-categoryA>});
// or
this.router.navigate(['/categoryB'], { relativeTo: <route-of-categoryA>});
不幸的是, relativeTo
只接受ActivatedRoute
對象,而我所擁有的只是ActivatedRouteSnapshot
和RouterStateSnapshot
。 有沒有辦法相對於目標路線進行導航(在這種情況下為 categoryA )? 任何幫助將不勝感激。
筆記:
this.router.navigateByUrl
使用state.url
。 我想使用router.navigate([...], { relativeTo: this-is-what-need})
。 事實證明,與Component等其他地方相比,構造函數注入ActivatedRoute
在RouteGuard中的工作方式有所不同。
在組件中, ActivatedRoute
對象指向激活該組件的路由。 例如,在CategoryAComponent
類中,以下代碼將導航到CategoryB :
this.router.navigate([ '../CategoryB' ], { relativeTo: this.route });
但是,以上相同代碼在添加到CategoryA路由配置的RouteGuard
類中RouteGuard
。 在我的測試中,我發現構造函數注入的ActivatedRoute
對象指向根路由。 另一方面, ActivatedRouteSnapshot
對象(在canActivate函數中作為參數傳遞)指向目標路由(在我的情況下為categoryA )。 但是,我們無法在this.router.navigate(...)
函數中傳遞此ActivatedRouteSnapshot
對象。
我找不到解決此問題的更好方法,但是以下代碼對我有用:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
return this.myService.checkPermission()
.then(result => {
if (!result.hasAccess) {
//redirect here
let redirectTo = route.pathFromRoot
.filter(p => p !== route && p.url !== null && p.url.length > 0)
.reduce((arr, p) => arr.concat(p.url.map(u => u.path)), new Array<string>());
this.router.navigate(redirectTo.concat('categoryB'), { relativeTo: this.route });
}
return result.hasAccess;
});
}
我可以為您提供一個更精簡的解決方案:
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): true | UrlTree {
const urlTree = createUrlTreeFromSnapshot(route, ['categoryB']);
return result.hasAccess || urlTree;
}
使用此解決方案,您可以輕松設置所有其他可能需要的道具 - 命名插座導航、查詢參數、片段...
如果您位於/ product / CategoryA,並且想要導航到/ product / CategoryB,則可以使用相對導航:
this.router.navigate([ '../CategoryB' ], { relativeTo: this.route });
您可以使用 Angular 14 中的新createUrlTreeFromSnapshot() function,如下所示:
const urlTree = createUrlTreeFromSnapshot(routeSnapshot, ['../categoryB']);
this.router.navigateByUrl(urlTree);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.