首页 > 解决方案 > Angular 8 边缘案例:ActivatedRoute#data 上的奇怪值(在父级上解析,在子级上的数据 => 子级数据被覆盖)

问题描述

我在实现一个简单的面包屑组件时偶然发现了这个问题。

这个想法是breadcrumb在路线的data属性上附加数据。对于静态值,效果很好:

const routes: Route[] = [
  // ...
  { path: 'outer', data: { breadcrumb: 'outer' }, component: OuterComponent, children: [
    { path: '', pathMatch: 'full', data: { breadcrumb: 'inner' }, component: InnerComponent }
  ] }
  // ...
];

这给了我'outer''inner'对应ActivatedRoute的s。

对于动态值,解析器服务似乎是一个很好的解决方案。如果不是一个(奇怪的?)边缘情况,这也很有效:

const routes: Route[] = [
  // ...
  { path: 'outer', resolve: { breadcrumb: OuterResolverService }, component: OuterComponent, children: [
    { path: '', pathMatch: 'full', data: { breadcrumb: 'inner' }, component: InnerComponent }
  ] },
  // ...
];

这给了我'outer''outer'(再次)对应ActivatedRoute的 s。这让我很惊讶。

注意:当内部组件有任何路径但''. pathMatch: 'full'似乎不是影响因素。我发现以下配置是一种可行的解决方法:

{ path: 'outer', resolve: { breadcrumb: 'outer' }, component: OuterComponent, children: [
  { path: 'inner', data: { breadcrumb: 'inner' }, component: InnerComponent },
  { path: '', pathMatch: 'full', redirectTo: 'inner' }
]}

尽管如此,它还是让我想知道:

作为参考,stackblitz 演示了该问题:Stackblitz

标签: angularangular8angular-router

解决方案


Angular 提供了 2 种路由参数继承模式,默认是emptyOnly指只有空路径继承其父参数(参数包括数据和解析数据)。(另一种模式是always这意味着孩子总是继承父参数,这对你没有帮助)

在这种情况下,您有一个空的子路径,因此它继承了它的父参数,但是,通常,如果子数据具有匹配的键,则子数据应该优先于继承的数据,就像在您的静态数据案例中一样。

但是,问题是解析的数据总是覆盖静态数据,无论是否继承(如果你有静态数据和解析数据在同一条路由上具有相同的键,无论出于何种原因,静态数据都会被覆盖),所以解析的数据是在已解析的父数据情况下覆盖子数据,但在静态情况下不会。或者,如果您在两个级别都有解析器,则孩子的解析数据将优先。

所以这不是一个“错误”,而是一个古怪/奇怪的行为。也许值得用角度来提高,因为优先顺序似乎是:子解析数据,父解析数据,子数据,父数据......什么时候应该(对我来说):子解析数据,子数据,父解析数据,父数据。尽管我可以看到任何一种方式的争论,因为孩子在技术上继承了父母解析的数据,这些数据应该会覆盖任何静态数据。

解决方法是有效的,因为从技术上讲,您的子路径并不是一条空路径。你只是在欺骗路由器不让孩子继承。

您可以使用的一个稍微不同的解决方法是只使用不同的关键字并让您感兴趣的面包屑组件检查两者,如下所示:

  { 
    path: 'not-working', 
    component: OuterComponent, 
    resolve: { resolvedBreadcrumb: OuterResolverService }, 
    children: [
      { 
        path: '', 
        pathMatch: 'full', 
        component: InnerComponent, 
        data: { breadcrumb: 'inner' }
      }
    ]
  },

和:

const crumb = route.snapshot.data['breadcrumb'] || route.snapshot.data['resolvedBreadcrumb'];

如下所示:https ://stackblitz.com/edit/angular-pmw6x1?file=src%2Fapp%2Fapp.module.ts


推荐阅读