angular 11.2.9 routerLink 不会重新初始化相同的组件

angular 11.2.9 routerLink doesn't re-initialise same component

我做错了什么,但找不到解决这个问题的确切方法。

我有一个带有视图组件的路由器 A:

const routes: Routes = [
  { path: '', redirectTo: '/list', pathMatch: 'full' },
  { path: 'list', component: ListComponent },
  { path: 'a/:id/:version', component: AComponent, resolve: { a: DataResolver}, runGuardsAndResolvers: 'always' }
];

一切正常 - 我正在导航到 A 组件 /a/1/v1 - 一切都已完美初始化。

问题:组件正在加载视图内容的其他版本的功能,我希望如果我只是在 A 组件视图中的某处单击 <a routerLink="/a/1/v2">load version 2</a>,该视图是重生了。

实际情况是

有趣的是,如果我配置 /b/.. 并将其分配给路由器配置中相同的 A 组件,从 /a/1/v1 导航到 [=22 后,一切都按预期工作=].

const routes: Routes = [
  { path: '', redirectTo: '/list', pathMatch: 'full' },
  { path: 'list', component: ListComponent },
  { path: 'a/:id/:version', component: AComponent, resolve: { a: DataResolver}, runGuardsAndResolvers: 'always' },
  { path: 'b/:id/:version', component: AComponent, resolve: { a: DataResolver}, runGuardsAndResolvers: 'always' },
];

我有点迷茫。感谢您的帮助。

在导航到您的组件时未调用构造函数和 ngOnInit 的原因源于 Angular 的默认值 RouteReuseStrategy

This base route reuse strategy only reuses routes when the matched router configs are identical. This prevents components from being destroyed and recreated when just the fragment or query parameters change (that is, the existing component is reused).

换句话说,因为只有 URL 的片段发生了变化,/a/1/v1 -> /a/1/v2,Angular 试图聪明地重用组件。这可以防止构造函数和 ngOnInit 再次被调用。 (我知道,真气,对吧?)

我能想到几个解决方案。

  1. 监听路由参数何时更改并处理回调中的任何初始化逻辑。这意味着您需要订阅可观察到的路由参数,并将最初在 ngOnInit 中的逻辑移动到订阅中。
class AComponent implements OnInit {
    constructor(private _route: ActivatedRoute) {}
    
    ngOnInit(): void {
        this._route.params.subscribe(newParams => {
             // handle any initialization logic here.
        }); 
    }

}
  1. 您可以用自己的 Angular 默认 RouteReuseStrategy 覆盖,以防止 Angular 重复使用路由组件。这是我们最终采用的方法。很容易忘记这个 Angular “功能”。您可以像这样覆盖默认路由重用策略。
export class MyCustomRouteReuseStrategy implements RouteReuseStrategy {
  // Never reuse a component!
  shouldReuseRoute(): boolean {
    return false;
  }

  // Implement the other default methods. Keep same functionality.
  shouldDetach(): boolean { return false; }
  store(): void {}
  shouldAttach(): boolean { return false; }
  retrieve(): DetachedRouteHandle | null { return null; }
}

// app.module.ts
@NgModule({
  providers: [
    { provide: RouteReuseStrategy, useClass: MyCustomRouteReuseStrategy },
  ]