Ionic/Angular 嵌套 router-outlet: routerLinks 只工作一次

Ionic/Angular nested router-outlet: routerLinks only work once

我正在尝试使用 Angular's routing guide 在 Angular Ionic v5 应用程序中实现 nested/child 路由的简单示例。我使用 ionic start 创建了一个项目并选择了 blank 模板,然后创建了两个组件 ChildAComponentChildBComponent。这是来自 home.page.html:

的相关代码片段
<div id="container">
  <strong>Ready to create an app?</strong>
  <p>Start with Ionic <a target="_blank" rel="noopener noreferrer"
      href="https://ionicframework.com/docs/components">UI Components</a></p>
  <div id="stuff">
    <a routerLink="child-a">Child A</a><br>
    <a routerLink="child-b">Child B</a><br>
    <a routerLink="404">404</a>
  </div>
  <div id="thing">
    <router-outlet></router-outlet>
  </div>
</div>

我正在尝试使用 a 标签来驱动 router-outlet 中呈现的组件。当我第一次加载页面 (URL: /home) 时,我可以单击其中一个 link,相应的 child 元素会在出口中呈现。 发生这种情况时,不过,a 标签上的 href(我假设它是由 Angular 根据 routerLinks) 全部改到navigated-to URL.

因此,如果不重新加载页面(返回 /home),我无法单击另一个组件 link 来呈现该组件。

在单击 link 之前(URL 是 /home):

点击后Child一个link(URL是/home/childa):

Angular 文档似乎没有表明我配置有误,而且与 heroes example 中的路由相比,我的代码中没有任何明显不同。我做错了什么?

这是我的 home-routing.module.ts 如果有帮助的话:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomePage } from './home.page';
import { ChildAComponent } from './childa/childa.component';
import { ChildBComponent } from './childb/childb.component';

const routes: Routes = [
  {
    path: '',
    component: HomePage,
    children: [
      {
        path: 'child-a',
        component: ChildAComponent,
      },
      {
        path: 'child-b',
        component: ChildBComponent,
      },
    ]
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class HomePageRoutingModule {}

GitHub: https://github.com/zrev2220/router-link-bug

简答

您必须将 绝对路径 添加到 RouterLink 指令中:

<a [routerLink]="['/home', 'child-a']">Child A</a><br>
<a [routerLink]="['/home', 'child-b']">Child B</a><br>

详细解答

让我们先了解一下RouterLink(特别是RouterLinkWithRef)指令是如何工作的。它将导航到的路线取决于当前激活的路线(ActivatedRoute)。这是 what happens 当您单击带有 RouterLinkWithRef 指令的元素时(例如 selector: 'a[routerLink]'):

/* ... */
this.router.navigateByUrl(this.urlTree, extras);
/* ... */

其中 this.urlTree 定义为 getter:

get urlTree(): UrlTree {
  return this.router.createUrlTree(this.commands, {
    relativeTo: this.route, // !
    queryParams: this.queryParams,
    fragment: this.fragment,
    preserveQueryParams: attrBoolValue(this.preserve),
    queryParamsHandling: this.queryParamsHandling,
    preserveFragment: attrBoolValue(this.preserveFragment),
  });
}

我们可以看到,有relativeTo: this.route,其中this.routeinjected as ActivatedRoute

这就是问题出现的原因:当当前路由为/home时,指令中注入的激活路由应该与来自/home/child-*的路由不同;在这种情况下,它是相同的。

因此,当用户首次登陆/home时,指令中注入的ActivatedRoute将具有一定的值,我们称之为X。但是当用户转到 /home/child-a 时,router-outlet 之外的视图保持不变,ActivatedRoute 的值也是如此。这很重要,因为在处理绝对和相对路由路径时(提供给路由器指令的任何没有前缀 / 的东西),Angular 将遍历当前的 UrlTree(UrlTree = 作为字符串提供的路由路径的反序列化版本)并将尝试用新部分替换旧部分。
用户导航到 /home/child-a 后,然后在当前 UrlTree 中无法在指令中找到从当前 ActivatedRoute 创建的旧部​​分,因为 ActivatedRoute 不再对应于 actual 激活的路线,所以它是 outdated.