Angular 阻止 URL 导航但保留按钮导航

Angular prevent URL navigation but keep button navigation

我目前正试图阻止用户浏览 url 本身。用户应该只能使用按钮进行导航。

基本上我的路由是这样的:

    const routes: Routes = [
  { path: 'form', component: FormComponent},
  { path: '', redirectTo: '/form', pathMatch: 'full' },
  { path: 'attachment', component: AttachmentComponent },
  { path: 'inbox', component: InboxComponent},
  { path: 'summary', component: SummaryComponent },
  { path: 'answer/:id', component: SummaryComponent}
];  

所以基本上用户应该能够使用 url 本身导航到“/form”和 "answer/:id" 但所有其他路由如 attachment/inbox/summary 应该只能通过按钮访问(例如,用户继续 /form 并有一个指向附件和摘要的按钮,或者用户继续“/answer:id”并带有一个指向收件箱的按钮)。

我尝试的第一件事是在路由模块中设置以下参数(不设置守卫):

@NgModule({
  imports: [RouterModule.forRoot(routes, { initialNavigation: false })],
  exports: [RouterModule]
})

不可能通过 url 导航(这很好)并且可以使用按钮导航,但遗憾的是我无法打开我的 "form" 或 "answer" 路线,这是必要的.
我试过设置守卫 :

const routes: Routes = [
  { path: 'form', component: FormComponent},
  { path: '', redirectTo: '/form', pathMatch: 'full' },
  { path: 'attachment', component: AttachmentComponent , canActivate:[DirectAccessGuard]},
  { path: 'inbox', component: InboxComponent, canActivate: [DirectAccessGuard]},
  { path: 'summary', component: SummaryComponent, canActivate: [DirectAccessGuard]},
  { path: 'answer/:id', component: SummaryComponent}
];

后卫:

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router} from '@angular/router';
import { Observable } from 'rxjs';
@Injectable({
  providedIn: 'root'
})
export class DirectAccessGuard implements CanActivate {
  constructor(private router: Router) { }
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    // If the previous URL was blank, then the user is directly accessing this page
    return false;
  }
}

使用 url 打开 "form" 和 "answer" 是可能的,但无法使用按钮重定向到另一个组件。有道理,因为我总是返回错误。
所以我的问题是:是否有可能在我的守卫中获得目标 url?
如果我在 /form 上并且我想重定向到 /attachment 我知道我可以使用 this.router.url 获得“/form”但我想要目标 url(在这种情况下为“/attachment”)。 或者有没有其他方法可以解决我的问题?

是的,可以从 ActivatedRouteSnapshot 中获取目标 url in guard。 ActivatedRouteSnapshot 中的 routeConfig 属性 有一个路径 属性 给目标 url.

我已经按照上述场景进行了测试, 现在路线如下所示,

const routes: Routes = [
    { path: 'form', component: FormComponent },
    { path: '', redirectTo: '/form', pathMatch: 'full' },
    { path: 'attachment', component: AttachmentComponent, canActivate: [DirectAccessGaurd] },
    { path: 'inbox', component: InboxComponent, canActivate: [DirectAccessGaurd] },
    { path: 'summary', component: SummaryComponent, canActivate: [DirectAccessGaurd] },
    { path: 'answer/:id', component: SummaryComponent, canActivate: [DirectAccessGaurd] },
    { path: '**', component: NotfoundComponent }
]

所以,实际逻辑在 Gaurd 中,

import { Injectable } from '@angular/core';
import { CanActivate, RouterStateSnapshot, ActivatedRouteSnapshot, Router } from '@angular/router';
import { Observable } from 'rxjs';

@Injectable({
    providedIn: 'root'
})
export class DirectAccessGaurd implements CanActivate {

    constructor(private router: Router) { }
    canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {

        if(this.router.url === '/form') {
            if(next.routeConfig.path === 'attachment' || next.routeConfig.path === 'inbox') {
                return true;
            }
        }
        if(next.routeConfig.path === 'answer/:id') {
            return true; // To allow answer/:id route through url
        }
        if(this.router.url.startsWith('/answer/')) {
            if(next.routeConfig.path === 'summary') {
                return true;
            }
        }

        this.router.navigate(['/notfound'])
        return false;
    }
}

逻辑很简单, 首先我检查当前 url 是否为 '/form',然后检查目标 url 是附件还是收件箱,然后我分别重定向到那些。