在命名插座中传递参数不起作用 为什么它首先不起作用解决方案

如何解决在命名插座中传递参数不起作用 为什么它首先不起作用解决方案

伙计们,我在尝试使这段代码正常工作时遇到了一些麻烦。

基本上,我想将一些参数传递给嵌套且命名的 router-outlet

来自存储库:https://stackblitz.com/edit/angular-hsezw8-rp5ne9?file=src/app/crisis-center/crisis-list/crisis-list.component.html

我正在使用以下 routerLink

    <a [routerLink]="[{ outlets: { test: [ crisis.id] } }]">
      <span class="badge">{{ crisis.id }}</span>{{ crisis.name }}
    </a>
...
<router-outlet name="test"></router-outlet>

我的路线如下:

{
        path: '',component: CrisisListComponent,children: [
          {
            path: ':id',component: CrisisDetailComponent,canDeactivate: [CanDeactivateGuard],resolve: {
              crisis: CrisisDetailResolverService
            },outlet: 'test'
          },{
            path: '',component: CrisisCenterHomeComponent
          }
        ]
      }

在 stackoverflow 中搜索后,根据答案,这应该有效,但事实并非如此。有没有人对我缺少的东西有任何了解? 提前致谢

解决方法

编辑

我写了一篇文章,详细介绍了 Angular 11 附带的新修复:Angular Router: empty paths,named outlets and a fix that came with Angular 11


TLDR;

Working demo.


详细说明

为什么它首先不起作用

一个TLRD,因为具有(嵌套)空路径的命名插座并不总是运行良好(至少在旧版本中)。这是其中一种情况。

首先,重要的是要提及 Angular Router 如何处理路由及其更改。例如,它在名为 UrlTree1 的数据结构的帮助下跟踪当前 URL。 UrlTree 可以被认为是 URL 的反序列化版本,它是一个字符串。给定一个 UrlTree,将基于这个 UrlTree 遍历路由配置数组(以 DFS 方式)。 UrlTree 的根是另一个结构,UrlSegmentGroup:

constructor(
  /** The URL segments of this group. See `UrlSegment` for more information */
  public segments: UrlSegment[],/** The list of children of this group */
  public children: {[key: string]: UrlSegmentGroup}) {
forEach(children,(v: any,k: any) => v.parent = this);

如您所见,它类似于常规的树结构。 segments 数组中的 a 段包含 path(例如 'crisis-center')和给定路径的矩阵参数。至于 children 属性,其键是网点名称(例如 'test'),值是 UrlSegmentGroup 实例。通过使用这些结构,Angular Router 可以表示 URL 字符串并可以提供许多功能和自定义。

给定来自 crisis-center-routing.module.ts 的路由配置:

const crisisCenterRoutes: Routes = [
  {
    path: '',// (1)
    component: CrisisCenterComponent,children: [
      {
        path: '',// (2)
        component: CrisisListComponent,children: [
          {
            path: ':id',// (3)
            component: CrisisDetailComponent,canDeactivate: [CanDeactivateGuard],resolve: {
              crisis: CrisisDetailResolverService
            },outlet: 'test'
          },{
            path: '',component: CrisisCenterHomeComponent
          }
        ]
      }
    ]
  }
];

将路由配置对象与 UrlTree 匹配的 path: ':id' 大致如下所示:

// Note: For simplicity,I've only used the `path` to represent the `segments` property
UrlTree {
  // UrlSegmentGroup
  root: {
    children: {
      primary: {
        children: {
          primary: {
            children: {
              test: {
                children: {}
                segments: [1],// Matches (3)
              }
            },segments: [''],// Matches (1) and (2)
          }
        }
        segments: ['crisis-center'],}
    }
    segments: [],}
}

注意:出口的默认名称是 'primary'

上面的UrlTree可以这样实现:

<a [routerLink]="['/crisis-center',{ outlets: { primary: ['',{ outlets: { test: [crisis.id] } }] } }]">
  <span class="badge">{{ crisis.id }}</span>{{ crisis.name }}
</a>

虽然上述方法理论上应该有效,但实际上并没有。这是因为 '' 未被 消耗,当发生这种情况时,将选择 primary 插座。更具体地说,来自 '' primary: ['' ... 将与 (1) 匹配,但第二个 ''(from (2)) 不会被消耗。 然而,这似乎to be fixed in Angular v12

// At this point,not all paths of the `segment` array have been consumed.
// This time,the route's outlet is taken into account.
const matchedOnOutlet = getOutlet(route) === outlet;
const expanded$ = this.expandSegment(
    childModule,segmentGroup,childConfig,slicedSegments,matchedOnOutlet ? PRIMARY_OUTLET : outlet,true);

但是 this 是以前的样子:

// At this point,not all paths of the `segment` array have been consumed.
// As you can see,it always chooses the `primary` outlet
const expanded$ = this.expandSegment(
    childModule,PRIMARY_OUTLET,true);

由于您是旧版本,我们需要找到另一种方法。

类似的事情发生在当前的方法中:

<a [routerLink]="[{ outlets: { test: [ crisis.id] } }]">
  <span class="badge">{{ crisis.id }}</span>{{ crisis.name }}
</a>

但是这次导航不会成功,因为网点之间会出现不匹配。它会在 (2) 处失败,其中路由的出口为 primary,但此时根据当前 UrlSegmentGroup 的出口为 test

解决方案

首先,我注意到 CrisisCenterComponent 的作用不大:

<h2>CRISIS CENTER</h2>
<router-outlet></router-outlet>

所以,我们会摆脱它。这就是我们剩下的:

crisis-center-routing.module.ts

const crisisCenterRoutes: Routes = [
  {
    // path: '',// component: CrisisCenterComponent,// children: [
    //   {
        path: '',component: CrisisListComponent,component: CrisisDetailComponent,component: CrisisCenterHomeComponent
          }
        ]
      }
  //   ]
  // }
]

现在,由于 CrisisListComponent 充当容器,我们可以进行以下替换:

crisis-center-routing.module.ts

const crisisCenterRoutes: Routes = [
  {
    // path: '',// children: [
    //   {
        // path: '',// component: CrisisListComponent,// children: [
        //   {
            path: ':id',component: CrisisCenterHomeComponent
          }
      //   ]
      // }
  //   ]
  // }
]

app-routing.module.ts

  {
    path: 'crisis-center',loadChildren: () =>
      import('./crisis-center/crisis-center.module').then(
        mod => mod.CrisisCenterModule
      ),data: { preload: true },// !
    component: CrisisListComponent
  },

因此,不会有额外的 ''(正如我们所见,有时会导致问题)匹配。

视图中的 routerLink 将保持不变:

<a [routerLink]="[{ outlets: { test: [ crisis.id] } }]">
  <span class="badge">{{ crisis.id }}</span>{{ crisis.name }}
</a>

顺便说一下,现在当您选择一个危机中心时,CrisisCenterHomeComponent 也将处于活动状态。如果你想避免这种情况,你可以这样做:

crisis-center-routing.module.ts

/* ... */
  {
    path: ':id'
    component: CrisisDetailComponent,resolve: {
      crisis: CrisisDetailResolverService
    },outlet: 'test'
  },{
    path: '',// Uncomment this if you want these 2 Route objects
    // to be mutually exclusive(either one of them,not both at the same time)
    pathMatch: 'full',component: CrisisCenterHomeComponent
  }
/* ... */

1:Angular Router: Getting to know UrlTree,ActivatedRouteSnapshot and ActivatedRoute

如果您想阅读有关 Angular Router 及其内部工作原理/功能的更多信息,我建议:

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?