36

我有一个带有一个路由器插座的 Angular2 应用程序,该插座根据在侧面菜单中单击的链接显示不同的组件。

<router-outlet>包含如下所示的主要组件的标记

<div *ngIf="authenticated == false">
  <app-login></app-login>
</div>
<div *ngIf="authenticated">
  <div class="page home-page">
    <header class="header">
      <app-navbar></app-navbar>
    </header>
    <div class="page-content d-flex align-items-stretch">
      <div class="sidebar-container">
        <app-sidebar-menu></app-sidebar-menu>
      </div>
      <div class="content-inner">
      <app-page-header></app-page-header>
        <div id="sub-content">
          <router-outlet></router-outlet>
        </div>
        <app-footer></app-footer>
      </div>
    </div>
  </div>
</div>

如果单击Demo链接,将呈现演示组件,但如果随后单击Home链接,则会在 DOM 中将 home 组件呈现在演示组件的上方。单击它们几次将产生这样的 DOM

<div _ngcontent-c0="" id="sub-content">
    <router-outlet _ngcontent-c0=""></router-outlet>
  <app-home _nghost-c6="">...</app-home>
  <app-demo _nghost-c7="">...</app-demo>
  <app-home _nghost-c6="">...</app-home> <!-- Why so many here? Should be just either one <app-home> or <app-demo>  -->
  <app-demo _nghost-c7="">...</app-demo>
  <app-home _nghost-c6="">...</app-home>
  <app-demo _nghost-c7="">...</app-demo>
  <app-footer _ngcontent-c0="" _nghost-c5="">...</app-footer>
</div>

路线定义为

export const router: Routes = [
    { path: 'demo', component: DemoComponent, canActivate: [AuthGuard] },
    { path: 'home', component: HomeComponent, canActivate: [AuthGuard] }
]

为什么<router-outlet>在路由之间切换时没有替换组件,而是添加了组件的另一个“实例”?

4

6 回答 6

55

通过排除的方法,我发现问题的罪魁祸首是BrowserAnimations我的app.module.ts. 通过从我imports的它中删除它,问题就消失了。我将研究创建一个 Plunker 来演示它。

更新: 这在这个Github issue中有描述。

2017 年 12 月 13 日更新: 此 PR 现已修复此问题,修复(动画):发生 CD 故障时正确恢复和清理 DOM

于 2017-08-13T13:19:04.890 回答
25

组件 A 抛出错误时也会发生这种情况,因此当导航到组件 B 时,组件 A 无法因错误而被销毁。这是 Angular 的一个错误。在他们修复之前,找到引发错误的原因并修复它。检查您的开发工具控制台。

于 2017-10-18T17:50:38.467 回答
7

我有一个非常相似的问题,也使用 Firebase。

查看附加到路由器插座的组件

但是,我发现问题来自我的一个组件中的错误,与我的路由无关。其中一个组件引用了“FormsArray”,该组件未使用且格式错误。它在 devtools 控制台中抛出了错误,但我没想到在那里检查,因为一切都编译得很好。

不确定这是否会帮助任何人。

于 2017-08-18T01:14:51.997 回答
3

我在组件中使用 NgZone 并且我的 routerLink 遇到了同样的问题,控制台内没有任何错误。

将 routerLink 更改为(单击)内部并调用如下函数:

constructor(
    (...)
    private zone: NgZone,
    (...)
  ) { }

goToPage() {
    this.zone.run(() => this.router.navigate(['/page']));
}
于 2017-11-27T11:45:52.403 回答
1

我有一个类似的问题,原因是我使用了一个未在组件 A 中声明的指令,并且在编译或控制台中没有错误。因此,当导航到组件 B 时,路由器正在附加内容。

为了调试,我注释掉了两个组件中的所有 html 标记,只留下一个 h1 来查看内容是否附加。通过一些测试,我找到了该指令并通过删除它,路由器再次恢复正常。

于 2018-06-04T14:50:07.540 回答
0

我不确定这是否完全符合您的情况,但是当我尝试加载不同的路由时,我已经将以前的组件附加到 DOM,最后我发现使用Hash与组件的地址冲突,

export const AppRouting = RouterModule.forRoot(routes, { useHash: false });

这解决了我所有不需要的附加组件的问题

于 2017-10-30T15:16:33.743 回答