【问题标题】:Angular 11 cannot route to named outletAngular 11 无法路由到命名出口
【发布时间】:2021-03-15 12:42:13
【问题描述】:

我们有一个带有 2 个选项卡的基本应用程序,每个选项卡都有自己的命名插座

<mat-tab-group>
    <mat-tab label="Tab1">
        <router-outlet name="tab1"></router-outlet>
    </mat-tab>
    <mat-tab label="Tab2">
        <router-outlet name="tab2"></router-outlet>
    </mat-tab>
</mat-tab-group>

2 个命名的 outlet 之一只是渲染一个组件,这很好。对于第二个,我们希望能够在不同视图之间进行路由,因此我们创建了自己的模块并延迟加载它。

应用路由看起来像

const routes: Routes = [{
    path: '',
    children: [{
        path: '',
        redirectTo: '/home',
        pathMatch: 'full'

    }, {
        path: 'login',
        loadChildren: () => import('./login/login.module').then(m => m.LoginModule)
    },
    {
        path: 'home',
        loadChildren: () => import('./home/home.module').then(m => m.HomeModule)
    }]
}]

首页的路由看起来像

const routes: Routes = [{
    path: '',
    component: HomeComponent,
    children: [{
        path: '',
        component: Tab1Component,
        outlet: 'tab1'
    }, {
        path: '',
        outlet: 'tab2',
        loadChildren: () => import('./tab2/tab2.module').then(m => m.Tab2Module)
    }]
}];

Tab2Module 实现如下

const routes: Routes = [{
    path: '',
    component: Tab2Child1Component
}, {
    path: 'tab2-child',
    outlet: 'tab2',
    component: Tab2Child2Component
}]

Tab2Child1Component 渲染良好,但我们无法导航到 Tab2Child2Component。

我正在尝试以下方法:

this.router.navigate([{ outlets: { tab2: 'tab2-child' } }], { relativeTo: this.route });

我可以在跟踪中看到路由器确实在尝试路由到 /home/(tab2:tab2-child),但最后它只是重定向回 /home 并出现错误:

 Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'home'
Error: Cannot match any routes. URL Segment: 'home'

Stackblitz 展示错误: https://stackblitz.com/edit/angular-ivy-pv5jsi

【问题讨论】:

  • 嘿,我不确定我是否理解正确,您希望它路由到:https://angular-ivy-w8jqek.stackblitz.io/home;tab2=tab2-child 吗?

标签: angular routes


【解决方案1】:

您的设计有两个问题导致它无法工作。

  1. 您的 home 组件的路径为空,不适用于命名的 outlet。它们仅在组件的路径被命名时才起作用。也许这会在未来改变,因为有一个open bug regarding this in the Angular GitHub
  2. 在命名出口中显示的组件必须是包含路由配置中出口的组件的直接子级。您对 tab2 使用 loadChildren 的配置就像 tab2 内部的组件将有更多内部路由,这在您的情况下是不正确的,因为您在 Tab2Child1Component 中没有另一个路由器出口。

要将您的示例更改为有效的内容,您需要在HomeModule 中添加指向HomeComponent 的路径。要延迟加载选项卡,您需要将所有选项卡放在一个模块中,该模块作为主组件的子级加载。

这是我对 HomeModule 的实现以及所需的更改。

const routes: Routes = [
  {
    path: '',
    redirectTo: 'hc',
    pathMatch: 'full'
  },
  {
    path: 'hc',
    component: HomeComponent,
    loadChildren: () => import("./tab.module").then(m => m.TabModule)
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  declarations: [HomeComponent]
})
export class HomeModule {}

以及为两个出口定义选项卡的选项卡模块的实现。

const routes: Routes = [
  {
    path: '',
    component: Tab1Component,
    outlet: "tab1"
  },
  {
    path: '',
    outlet: 'tab2',
    component: Tab2Child1Component
  },
  {
    path: 'tab2-child',
    outlet: 'tab2',
    component: Tab2Child2Component
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  declarations: [Tab2Child1Component, Tab2Child2Component]
})
export class TabModule {}

在应用程序模块中,由于某种原因直接重定向到子路径,如果您仅重定向到主页,则模块中的重定向不起作用。

 {
   path: "",
   redirectTo: "/home/hc",
   pathMatch: "full"
 },

这里是指向a fork of your StackBlitz 的完整实现链接。

如果您需要为每个选项卡具有单独的延迟加载模块,那么您需要为每个选项卡创建单独的组件,其中每个选项卡内部都有一个路由器插座以显示选项卡子组件,以便您获得两级导航结构。由于我不知道您的确切用例是什么,所以我不能说这是否是一个更好的解决方案。

【讨论】:

  • 我相信 (1) 已在 Angular 11 中得到修复,即您现在可以为命名的网点设置空路径。您的分叉版本似乎对我不起作用,即我仍然遇到相同的路由错误。最后,我确实将所有路由移到了 home 组件下的平面列表中。我不介意它们是否延迟加载,这不是很大的开销。我只是想将 2 个选项卡路由配置分开。
  • 我已经修复了我的样本。显然,第一个问题在 Angular 11 中没有得到解决,因为我忘记为路由添加名称并且它不起作用。现在加上名字就可以了。
  • 我将此答案标记为正确答案,因为它与我自己最终选择的答案几乎相同。
猜你喜欢
  • 1970-01-01
  • 2018-02-10
  • 2016-10-27
  • 1970-01-01
  • 2019-05-17
  • 2021-08-05
  • 2018-04-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多