我们在此处提供了儿童路线定义,其中我们使用警卫来检查用户在使用我们的服务之前是否接受了条款。
帐户/秘密/ secret.routes.ts:
import { Routes } from '@angular/router';
import { SecretFormComponent } from './secret-form.component';
import { SecretTermsComponent } from './secret-terms.component';
import { TermsGuard } from './services/terms-guard.service';
export const secretRoutes: Routes = [
{
path: '',
redirectTo: 'form'
},
{
path: 'form',
component: SecretFormComponent,
canActivate: [TermsGuard]
},
{ path: 'terms', component: SecretTermsComponent }
// otherwise redirect to form
{ path: '**', redirectTo: 'form' }
];
在我们的术语守护中,我们定义了以下代码:
this.router.navigate(['/account/secret/terms']);
return false;
有没有办法在“路由组”中使用相对路由导航重定向?因为如果有一天我们的帐户网站仪表板被重命名为my-account等其他任何东西,那么定义绝对路径可能会中断。我们希望我们的秘密模块可以重复使用。
我希望能够在我的后卫中导航到['./terms']
,但它不起作用,就像守卫不知道“从哪里”开始相对导航。
你想要使用的是你的后卫的RouterStateSnapshot
方法的canActivate
参数。
RouterStateSnapshot
具有您在路由过程中的当前路径,而Router.url
是您路由的当前路径(这就是为什么@Günter Zöchbauer的答案在这种情况下不起作用的原因)。
为了完全适用于您的用例而没有其他代码,您将需要更改您的路由
/account/secret/form
和/account/secret/form/terms
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class ChildRouteGuard implements CanActivate {
constructor(private router: Router) { }
canActivate(_route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
if (// user can view the specific route) {
return true;
}
// else route them to a variation of the route
this.router.navigate([state.url, 'terms']);
return false;
}
}
你可以利用ActivatedRouteSnapshot
来保持你当前的网址结构,如下所示
假设像account/secret/form
和account/secret/terms
这样的路线
route.url
是一个url段的数组,我们想要最后一个因为那将是form
。我们找到当前路线中的指数我们试图去account/secret/form
和slice
它。在这一点上,我们有当前路线的'父母',我们正试图导航到account/secret
,我们可以添加兄弟姐妹到form
,这是terms
。
注意:当您的网址中重复出现form
时,此模式会崩溃
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class ChildRouteGuard implements CanActivate {
constructor(private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
if (// user can view the specific route) {
return true;
}
let parentUrl = state.url
.slice(0, state.url.indexOf(route.url[route.url.length - 1].path));
this.router.navigate([parentUrl, 'terms']);
return false;
}
}
你应该能够从state.url获取你试图导航到的url,使用提供的urlSerializer解析它,然后在你需要的新urlSegment中拼接相对于guard所匹配的内容。
export class TermsGuard implements CanActivate<SecretFormComponent>{
constructor(private router: Router, private urlSerializer: UrlSerializer) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
let routerStateUrlTree = this.urlSerializer.parse(state.url);
let newSegment = new UrlSegment('terms', {});
routerStateUrlTree.root.children.primary.segments.splice(-1, 1, newSegment);
this.router.navigateByUrl(routerStateUrlTree);
return false;
}
}
你说“我希望能够导航到['./terms']”,但根据你的路线,我认为你的意思是['../terms'],但如果你的确意味着['./terms''只需将拼接的第二个参数更改为0,这样就不会删除最后一个段。
router具有保存当前url的url属性。你可以追加你的。
this.router.navigate([this.router.url,'terms']);
您需要使用当前路线(如ActivatedRoute
)创建相对于此路线的UrlTree
。然后你可以使用这个UrlTree
与this.router.navigateByUrl(...)
:
let urlTree = this.router.createUrlTree(['./terms'], {relativeTo: this.route});
this.router.navigateByUrl(urlTree);
如果你想用Resolve<T>
方法做,你可以这样做。
我认为同样适用于任何一种防守 - 使用pathFromRoot
。
此示例删除最后一个'segment'(即-1
)并添加"XXXXXXXX"
。
resolve(route: ActivatedRouteSnapshot) {
const fullPathFromRoot = route.pathFromRoot.reduce<string[]>((arr, item) => ([...arr, ...item.url.map(segment => segment.path)]), []);
const newUrl = [ ...fullPathFromRoot.slice(0, -1), "XXXXXXXX" ];
this.router.navigate(newUrl);
}
route
是给你的路线 - 不要试图注射ActivatedRoute
,因为这是行不通的。