サイドメニューでクリックされたリンクに応じて異なるコンポーネントを表示する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>
はコンポーネントを置き換えず、代わりにルートを切り替えるときにコンポーネントの別の「インスタンス」を追加するのですか?
除去の方法を使用して、問題の原因はapp.module.ts
のBrowserAnimations
モジュールであることがわかりました。 imports
から削除することで、問題はなくなりました。 Plunkerを作成して、それをデモンストレーションします。
更新:これは、この Github問題 で説明されています。
2017-12-13の更新:これはこのPRで修正されました、 fix(animations):適切に回復およびクリーンアップCDエラーが発生したときのDOM 。
これは、コンポーネントAがエラーをスローしているの場合にも発生するため、コンポーネントBに移動すると、エラーのためコンポーネントAを破棄できませんでした。これはAngularのバグです。修正されるまで、スローされるエラーの原因を見つけて修正します。開発ツールコンソールを確認してください。
Firebaseを使用しても、同様の問題が発生しました。
ただし、この問題はルーティングに関係なく、コンポーネントの1つにあるエラーが原因であることがわかりました。コンポーネントの1つに「FormsArray」への参照がありましたが、使用されておらず、不正な形式でした。 devtoolsコンソールにエラーがスローされましたが、すべてが正常にコンパイルされているため、そこでチェックすることは考えませんでした。
それが誰かを助けるかどうかわからない。
コンポーネント内でNgZoneを使用していましたが、コンソール内でエラーが発生せずにrouterLinkで同じ問題が発生していました。
RouterLinkを内部(クリック)に変更し、次のような関数を呼び出しました。
constructor(
(...)
private zone: NgZone,
(...)
) { }
goToPage() {
this.zone.run(() => this.router.navigate(['/page']));
}
私は同様の問題を抱えていましたが、その理由はコンポーネントAで宣言されていないディレクティブを使用し、コンパイルまたはコンソールにエラーがなかったためです。そのため、コンポーネントBに移動すると、ルーターはコンテンツを追加していました。
デバッグするために、両方のコンポーネントのすべてのhtmlマークアップをコメントアウトして、コンテンツが追加されているかどうかを確認するためにh1のみを残しました。いくつかのテストでディレクティブを見つけ、それを削除することで、ルーターを再び通常に戻しました。
これがあなたの状況と正確に一致するかどうかはわかりませんが、別のルートをロードしようとするときに以前のコンポーネントがDOMに追加され、最後にHash
の使用がコンポーネントのアドレスと競合することがわかりました、
export const AppRouting = RouterModule.forRoot(routes、{seHash:false});
これにより、不要な追加コンポーネントに関するすべての問題が修正されました