web-dev-qa-db-ja.com

Angular2ルーターは、コンポーネントを置き換える代わりに追加します

サイドメニューでクリックされたリンクに応じて異なるコンポーネントを表示する1つのルーターアウトレットを持つ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>

デモリンクをクリックすると、デモコンポーネントが表示されますが、ホームリンクをクリックすると、DOMのデモコンポーネントの上にホームコンポーネントが表示されます。それらを数回クリックすると、このような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>はコンポーネントを置き換えず、代わりにルートを切り替えるときにコンポーネントの別の「インスタンス」を追加するのですか?

33
Daniel B

除去の方法を使用して、問題の原因はapp.module.tsBrowserAnimationsモジュールであることがわかりました。 importsから削除することで、問題はなくなりました。 Plunkerを作成して、それをデモンストレーションします。

更新:これは、この Github問題 で説明されています。

2017-12-13の更新:これはこのPRで修正されました、 fix(animations):適切に回復およびクリーンアップCDエラーが発生したときのDOM

53
Daniel B

これは、コンポーネントAがエラーをスローしているの場合にも発生するため、コンポーネントBに移動すると、エラーのためコンポーネントAを破棄できませんでした。これはAngularのバグです。修正されるまで、スローされるエラーの原因を見つけて修正します。開発ツールコンソールを確認してください。

20
TetraDev

Firebaseを使用しても、同様の問題が発生しました。

ルーターアウトレットに追加されるコンポーネントを参照

ただし、この問題はルーティングに関係なく、コンポーネントの1つにあるエラーが原因であることがわかりました。コンポーネントの1つに「FormsArray」への参照がありましたが、使用されておらず、不正な形式でした。 devtoolsコンソールにエラーがスローされましたが、すべてが正常にコンパイルされているため、そこでチェックすることは考えませんでした。

それが誰かを助けるかどうかわからない。

6

コンポーネント内でNgZoneを使用していましたが、コンソール内でエラーが発生せずにrouterLinkで同じ問題が発生していました。

RouterLinkを内部(クリック)に変更し、次のような関数を呼び出しました。

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

goToPage() {
    this.zone.run(() => this.router.navigate(['/page']));
}
2
António Santos

私は同様の問題を抱えていましたが、その理由はコンポーネントAで宣言されていないディレクティブを使用し、コンパイルまたはコンソールにエラーがなかったためです。そのため、コンポーネントBに移動すると、ルーターはコンテンツを追加していました。

デバッグするために、両方のコンポーネントのすべてのhtmlマークアップをコメントアウトして、コンテンツが追加されているかどうかを確認するためにh1のみを残しました。いくつかのテストでディレクティブを見つけ、それを削除することで、ルーターを再び通常に戻しました。

1
Hassan Juniedi

これがあなたの状況と正確に一致するかどうかはわかりませんが、別のルートをロードしようとするときに以前のコンポーネントがDOMに追加され、最後にHashの使用がコンポーネントのアドレスと競合することがわかりました、

export const AppRouting = RouterModule.forRoot(routes、{seHash:false});

これにより、不要な追加コンポーネントに関するすべての問題が修正されました

0
Jaime Gonzalez