ActivatedRoute 不会在路线更改时更新子路线数据

Bod*_*ody 4 angular-routing angular angular-activatedroute angular8

我正在尝试使用ActivatedRoute. 我已经尝试了以下示例,并且能够获得我正在寻找的数据,但只能获得一次。在子路由更改期间,我没有看到更新的“布局”值。

路线

const routes: Routes = [
  {
    path: '',
    component: Layout1Component,
    children: [
      {
        path: '',
        redirectTo: 'home',
        pathMatch: 'full'
      },
      {
        path: 'home',
        loadChildren: './pages/analytics/analytics.module#AnalyticsModule',
        data: {
          layout: 'boxed'
        }
      },
      {
        path: 'files',
        loadChildren: './pages/files/files.module#FilesModule',
        data: {
          layout: 'full'
        }
      }
    ]
  }
];
Run Code Online (Sandbox Code Playgroud)

布局1组件

export class Layout1Component implements OnInit {
  constructor(private service: AppService, route: ActivatedRoute) {
    this.layout = route.snapshot.firstChild.data['layout'];

    route.url.subscribe(() => {
      console.log(route.snapshot.firstChild.data['layout']);
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

我希望每次更改路线时都使用更新的“布局”值打印 console.log。

请帮我解决这个问题。

And*_*tej 5

根据我的理解,您只ActivatedRoute获取一次数据的原因是因为在实例化时将其url作为BehaviorSubject获取。

function createActivatedRoute(c: ActivatedRouteSnapshot) {
  return new ActivatedRoute(
      new BehaviorSubject(c.url), new BehaviorSubject(c.params), new BehaviorSubject(c.queryParams),
      new BehaviorSubject(c.fragment), new BehaviorSubject(c.data), c.outlet, c.component, c);
}
Run Code Online (Sandbox Code Playgroud)

这是上述代码段的链接

这意味着当您订阅时,您只会获得第一个存储的值。

解决它的一种方法是利用路由器事件

假设你有这样的事情:

const routes: Route[] = [
  { 
    path: '', 
    component: HelloComponent,
    children: [
      {
        path: 'foo',
        loadChildren: () => import('path/to/foo').then(m => m.FooModule),
        data: {
          name: 'andrei'
        }
      },
      {
        path: 'bar',
        loadChildren: () => import('path/to/bar').then(m => m.BarModule),
        data: {
          name: 'john'
        }
      },
    ]
  },
]
Run Code Online (Sandbox Code Playgroud)

这是一个可能的解决方案:

 constructor (private router: Router, private route: ActivatedRoute) { }

 ngOnInit () {
    const routeEndEvent$ = this.router.events
      .pipe(
        filter(e => e instanceof NavigationEnd),
        tap(() => console.warn("END")),
    );

    this.router.events
      .pipe(
        filter(e => e instanceof ChildActivationEnd && e.snapshot.component === this.route.component),
        buffer(routeEndEvent$),
        map(([ev]) => (ev as ChildActivationEnd).snapshot.firstChild.data),
        takeUntil(this.ngUnsubscribe$)
      )
      .subscribe(childRoute => {
        console.log('childRoute', childRoute);
      })
  }
Run Code Online (Sandbox Code Playgroud)
  • routeEndEvent$是一个 observable,只有在路由准备好时才会发出(NavigationEnd

  • filter(e => e instanceof ChildActivationEnd && e.snapshot.component === this.route.component): 在检查了路由器发出的事件一段时间后,我得到了这个解决方案来确定 component( HelloComponent)是否是this.route.component更改了的路由的 parent( )( e.snapshot.component)。

  • buffer(routeEndEvent$):我们只想在路由器达到其最终状态时采取行动(NavigationEnd)。在这里你可以阅读更多关于buffer运营商的信息

闪电战