Angular2 相对路径在警卫中导航
Posted
技术标签:
【中文标题】Angular2 相对路径在警卫中导航【英文标题】:Angular2 relative route navigate in a guard 【发布时间】:2017-04-21 02:28:02 【问题描述】:我们在此处提供了子路由定义,其中我们使用保护来检查用户在使用我们的服务之前是否已接受条款。
account/secret/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']
,但它不起作用,就像警卫不知道“从哪里”开始相对导航一样。
【问题讨论】:
【参考方案1】:你要使用的是你的守卫的canActivate
方法的RouterStateSnapshot
参数。
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
// user can view the specific route
if (...)
return true;
// else route them to a variation of the route
this.router.navigate([state.url, 'terms']);
return false;
编辑 1
您还可以利用ActivatedRouteSnapshot
来保持当前的网址结构,如下所示
假设像account/secret/form
和account/secret/terms
这样的路由
route.url
是一个 url 段数组,我们想要最后一个,因为那将是 form
。我们在我们试图去account/secret/form
和slice
的当前路线中找到它的索引。此时,我们有当前路线的“父”,我们试图导航到account/secret
,我们可以将兄弟添加到form
,即terms
。
注意:当您在 url 中重复出现 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
// user can view the specific route
if (...)
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;
【讨论】:
【参考方案2】:另一种方法是调整url
并使用navigateByUrl
。
import Injectable from "@angular/core";
import
CanActivate,
ActivatedRouteSnapshot,
RouterStateSnapshot,
Router,
from "@angular/router";
import AuthService from "../services/auth.service.ts";
@Injectable(
providedIn: "root",
)
export class AuthGuard implements CanActivate
constructor(
private authService: AuthService,
private router: Router
)
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): true | Promise<boolean>
if (this.authService.isLoggedIn)
return true;
const urlParts = state.url.split("/");
urlParts[urlParts.length - 1] = "login";
const newUrl = urlParts.join("/");
return this.router.navigateByUrl(newUrl);
【讨论】:
【参考方案3】:如果您想在 Resolve<T>
方法中执行此操作,您可以这样做。
我认为这同样适用于任何类型的守卫——使用pathFromRoot
。
此示例删除最后一个“段”(即-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
,因为那是行不通的。
【讨论】:
【参考方案4】:您应该能够从 state.url 中获取您尝试导航到的 url,使用提供的 urlSerializer 对其进行解析,然后将您想要的新 urlSegment 与防护匹配的内容拼接起来。
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,这样它就不会删除最后一段。
【讨论】:
以上是关于Angular2 相对路径在警卫中导航的主要内容,如果未能解决你的问题,请参考以下文章