Angular 带有延迟加载模块的路由器面包屑

Angular Router Breadcrumbs with Lazy Loaded Modules

我正在使用 Angular 路由器动态添加面包屑。我遵循了几个示例并使它们成功运行。

但是,如果我尝试合并延迟加载的模块,我会收到错误消息:

Root segment cannot have matrix parameters

我已经研究过那个问题,但未能找到令人满意的 information/fixes。

我已经创建了一个 plunk,其中包含我正在努力完成的工作,以节省此页面上的大量代码: https://plnkr.co/edit/505x2r

如何继续使用路由器的动态面包屑创建,同时使用延迟加载的路由。

import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';

import { RootComponent } from 'src/root/root.component';
import { IndexComponent } from 'src/index/index.component';
import { SignupComponent } from 'src/signup/signup.component';
import { SigninComponent } from 'src/signin/signin.component';

@NgModule({
    imports: [
        RouterModule.forChild([
            {
            path: '',
            component: RootComponent,
            children: [
                {
                    path: 'signin',
                    loadChildren: 'src/signin/signin.module#SigninModule'
                },
                {
                    path: 'signup',
                    component: SignupComponent,
                    data: {
                        breadcrumb: 'Sign Up'
                    }
                },
                {
                    path: '',
                    component: IndexComponent
                }
            ]
        }
    ])
],
exports: [
    RouterModule
]
})
export class RootRoutingModule {}

我发现了与该问题有关的几个因素,并将其付诸 'seemingly' 工作:

  • 您的方法 getBreadcrumbs() 在单个导航中被调用 3 次,这是一个问题。在函数开头加个console.log('I pass !');就可以看到了

  • 我认为主要问题是您使用了延迟加载模块的路径。对于面包屑组件,它将使用 SignUpModule 中的空路径。这就是中断的原因,因为您的面包屑组件将使用您当前激活的空路径('')的路径,并且会有效地中断路由,因为您没有连接 / 。在你的组件中更改这部分将使其首次工作,因为到延迟加载模块路径的路由将被注册,并且它将能够注册一个不为空的routerLink。

breadcrumb.component.ts

   let routeURL = child.snapshot.url.map(segment => segment.path).join('/');
   if(routeURL.length == 0) {
     routeURL = 'toto';
   }
   url += `/${routeURL}`;  
  • 因此你应该想办法为你的惰性加载模块使用一个空路由,这样 /signup 路径就是你在他的模块中的注册组件。路由就能正确注册了。

感谢 Robert、Alex Beugnet 和 DAG 的评论,让我走上正确的轨道,找到可靠的解决方案!

最后的内容在这里:https://plnkr.co/edit/iedQjH?p=preview

以下是我 运行 的浓缩问题:

首先,我有延迟加载的路线,我在路线上以面包屑的形式获得数据。 运行通过 getBreadcrumbs 时,面包屑标签会显示两次。我通过添加以下行解决了这个问题:

  if (
    child.snapshot.url.map(segment => segment.path).length === 0
  ) {
      return this.getBreadcrumbs(child, url, breadcrumbs);
  }

其次,我的路线只是一个参数输入,但我需要将其列在面包屑路径上。这已通过映射 child.snapshot.url 并将段分配给标签来解决。

const routeArray = child.snapshot.url.map(segment => segment.path);
for ( let i = 0; i < routeArray.length; i++ ) {
    label = routeArray[i];
}

第三,我需要显示下一条路线的参数和标签,无论它是立即加载还是通过模块延迟加载。我还 运行 进入以下需要拆分并适当分配标签的路径:

{
    path: ':id/products',
    loadChildren: 'src/products/products.module#ProductsModule',
    data: {
      breadcrumb: 'Products'
    }
}

                {
                  path: 'orders/:id',
                  component: OrderComponent,
                  data: {
                    breadcrumb: 'Orders'
                  }
                },

两者的解决方案是:

  for ( let i = 0; i < routeArray.length; i++ ) {
    if ( Object.keys(child.snapshot.params).length > 0 ) {
      if ( this.isParam(child.snapshot.params, routeArray[i]) ) {
        label = routeArray[i];
      } else {
        label = child.snapshot.data[ROUTE_DATA_BREADCRUMB];
      }
    } else {
      label = child.snapshot.data[ROUTE_DATA_BREADCRUMB];
    }
    const routeURL = routeArray[i];
    url += `/${routeURL}`;
    const breadcrumb: BreadCrumb = {
      label: label,
      params: child.snapshot.params,
      url: url
    };
    breadcrumbs.push(breadcrumb);
  }

private isParam(params: Params, segment: string) {
  for ( const key of Object.keys(params)) {
    const value = params[key];
    if ( value === segment ) {
      return true;
    }
  }
  return false;
}

尽管如此,但有一个问题:您必须为每个参数设置一个路径

例如,如果您有url:#/quotes/123456/products/123456/Generic/Tissue,您将需要以下路线:

{
  path: ':id',
  component: ProductComponent,
  data: 'data'
},
{
  path: ':id/:make',
  component: ProductComponent,
  data: 'data'
},
{
  path: ':id/:make/:model',
  component: ProductComponent,
  data: 'data'
}

你最终会得到一个如下所示的可点击面包屑:

主页/报价/123456/产品/123456/仿制药/纸巾

我正在从事的项目只需要一个参数...永远。

最后,我能够处理立即加载的路由和延迟加载的路由,这是我的最终目标。我确信有些情况我没有考虑到,但我觉得它非常可靠。

无论如何,我鼓励人们接受这里的东西 运行。给我发一条有任何更新的便条,这样我就能知道这还能变成什么!谢谢!