Angular "navigate" 到 404 但保留 url

Angular "navigate" to 404 but keep url

我已经检查了很多问题和互联网,但没有任何运气,所以也许有人有类似的问题...

我实现了一个延迟加载模块:

  {
    component: LoginPageComponent,
    path: '',
    pathMatch: 'full'
  },
  {
    canActivate: [AuthGuard],
    loadChildren: () => import('./modules/home/home.module').then(m => m.HomeModule),
    path: 'home'
  },

在 HomeRoutingModule 中我还有一个

....
 children: [
      ...
      {
        path: 'items',
        canActivate: [SomeGuard,
        loadChildren: () => ....
      },

然后终于在那个子懒加载模块路由:

{
    path: 'preview/:id',
    canActivate: [ItemLoadedGuard],
    component: PreviewPageComponent
  },

所以某些条目的 URL 将是例如:/home/items/preview/some-random-id。在那个 ItemLoaderGuard 中,我对该资源实施了 BE 调用,并在错误时导航到 404 页面。

但是当我通过这个实现时: /home/items/preview/wrong-id 我将被重定向到 /404 页面。

我想做的是保留 url 并打开 404 页面组件,这样: /home/items/preview/wrong-id 使用 NotFoundPageComponent 而不是 PreviewPageComponent

我试过使用导航附加功能,例如:skipLocationChangereplaceUrl 但没有效果。

除了在 PreviewPageComponent 中添加一些将显示未找到或未找到的包装器之外(下面的示例代码),还有其他方法可以解决这个问题吗?

<not-found *ngIf="displayNotFound"></not-found>
<div class="content" *ngIf="!displayNotFound">
....
</div>

我也在考虑将 url 存储在本地存储中,导航到 404 然后替换没有路径的 url,但也许有人有更好的解决方案?

演示版:https://stackblitz.com/edit/angular-404

将您的 preview.guard.ts 更改为

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

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

constructor(private router: Router){}

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    if(next.params.id === '123-works'){
      console.log('allowed')
      return true;
    } else {
      console.log('not allowed');
      setTimeout(() => this.router.navigateByUrl('404', {skipLocationChange: true}));
      return true;
    }
  }
}

工作原理

其实当你引用的时候,你之前的url是主页而不是'wrong-id',当守卫发送false时,之前的url变成了主页并且return是错误的将您带到上一个 url。我在这里所做的是允许 url 被激活,因为我在 settimeout 中一直路由到 404,它将在导航到 'wrong-id'

后启动