公式チュートリアル( https://angular.io/tutorial/ )に従ってangularを学習しようとしていますが、ヒーローコンポーネントとヒーロー詳細コンポーネントの手順に従うと、エラー「RangeError:最大呼び出しスタックサイズを超えました」。
hero.component.htmlと詳細コードは次のとおりです。
<ul class="heroes">
<li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero === selectedHero">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
</ul>
<!--
<app-hero-detail [hero]="selectedHero"></app-hero-detail> -->
<app-heroes></app-heroes>
詳細については:
<div *ngIf="hero">
<h2>{{hero.name}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div>
<label>name:
<input [(ngModel)]="hero.name" placeholder="name"/>
</label>
</div>
</div>
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
ヒーローコンポーネント
import { Component, OnInit } from '@angular/core';
import { Hero } from '../hero';
import { HEROES } from '../mock-heroes';
import { HeroService } from '../hero.service';
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
heroes: Hero[];
selectedHero: Hero;
constructor(private heroService: HeroService) { }
ngOnInit() {
this.getHeroes();
}
getHeroes(): void {
this.heroes = this.heroService.getHeroes();
}
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
}
hero.detailコンポーネント
import { Component, OnInit, Input } from '@angular/core';
import { Hero } from '../hero';
@Component({
selector: 'app-hero-detail',
templateUrl: './hero-detail.component.html',
styleUrls: ['./hero-detail.component.css']
})
export class HeroDetailComponent implements OnInit {
@Input() hero: Hero;
constructor() { }
ngOnInit() {
}
}
言及すべきことの1つは、<app-heroes></app-heroes>
がコメント化されると、リストページがエラーなしでロードされることです。
1.このエラーは、無限ループがある場合に発生します。 app-heroesがコメント化されたときにページがロードされることを述べたように、これは複数のコンポーネントのセレクタ名として使用される可能性がありますは許可されません。これにより、無限ループが発生し、コンポーネントのロードに失敗する可能性があります。
hero.component.html
<ul class="heroes">
<li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero === selectedHero">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
</ul>
<app-hero-detail [hero]="selectedhero"></app-hero-detail>
hero.detail.component.html
<div *ngIf="hero">
<h2>{{hero.name}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div>
<label>name:
<input [(ngModel)]="hero.name" placeholder="name"/>
</label>
</div>
</div>
お役に立てれば。
この例では、自分の内部でコンポーネントをレンダリングするため、この操作を終了することはなく、常に別の子コンポーネントをレンダリングします(ブロックの2番目の部分が
更新-詳細:
コンポーネントを使用してアプリを作成する場合、すべてのコンポーネントは階層的であるため、同じコンポーネントをループ内の制限された量であることが確実な場合にのみ、自分の内部に含めることができます。コード例では、子コンポーネントが自分の体内で次の子コンポーネントを生成するため、無制限のネストされたコンポーネントがあります。結果として、ブラウザの表示エラー:RangeError: Maximum call stack size exceeded
hero.component.html
<ul class="heroes">
<li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero === selectedHero">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
</ul>
<!--
<app-hero-detail [hero]="selectedHero"></app-hero-detail> -->
<app-heroes></app-heroes>
app-hero-details.component.html
<div *ngIf="hero">
<h2>{{hero.name}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div>
<label>name:
<input [(ngModel)]="hero.name" placeholder="name"/>
</label>
</div>
</div>
// you should comment line below
// <app-hero-detail [hero]="selectedHero"></app-hero-detail>
<app-hero-detail>
が詳細HTML内に表示されています。
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
これを削除してみてください。同様の行がhero.component.html
でコメントされていますが、コメントを外すことができます。
既存のアプリケーションをangular 8にアップグレードし、新しいルーティング機能を使用する場合、このエラーの別の原因を説明する回答を追加します。
私の場合、新しい構文を使用して、遅延ロードされた各ルートにdata
オブジェクトをpreload
をtrue || false
に設定して追加しました。
{
path: '',
loadChildren: () => import('./views/home/home.module').then(mod => mod.HomeModule),
data: { preload: true }
},
しかし、preloadingStrategy
forRoot宣言でPreloadAllModules
をRouterModule
に設定したままにしていたことに気付くまでに少し時間がかかりました。
@NgModule({
imports: [RouterModule.forRoot(
routes,
{
preloadingStrategy: PreloadAllModules, <-- This is the cause
})],
...
モジュールforRoot宣言からpreloadingStrategyを削除し、ルートデータのプリロードdefinitioに依存することで問題が修正されます。