Angular组件间通过Service传值遇TypeError错误求助
问题:Angular组件通过Service传递数据时出现
Cannot read properties of undefined (reading 'statistics')错误 错误信息
ERROR TypeError: Cannot read properties of undefined (reading 'statistics') at StatsComponent_div_2_Template
尝试过移除变量类型、在HTML中添加?运算符,错误消失但始终无法获取数据,以下是相关代码:
组件TypeScript代码
export class StatsComponent implements OnInit { myCharactere: ICharactere = this.myService.getPersonnageByName("Xefoul Snaromers"); statLookup = [ { key: 'str', prefix: $localize`str`, suffix: $localize`enght`, couleur: 'bg-danger' }, { key: 'dex', prefix: $localize`dex`, suffix: $localize`terity`, couleur: 'bg-primary' }, { key: 'con', prefix: $localize`con`, suffix: $localize`stitution`, couleur: 'bg-warning' }, { key: 'int', prefix: $localize`int`, suffix: $localize`elligence`, couleur: 'bg-success' }, { key: 'sag', prefix: $localize`wis`, suffix: $localize`dom`, couleur: 'bg-info' }, { key: 'cha', prefix: $localize`cha`, suffix: $localize`risma`, couleur: 'bg-dark' } ]; constructor(public myService: ServeurService) { } ngOnInit(): void { console.log("mon perso stats", this.myCharactere) } getModifier(stat: number): string { const mod = Math.floor((stat-10)/2) return (mod<0)?'-':'+'+ mod.toString(); } }
HTML代码
<div class="row text-center text-light bg-secondary mt-2 bg-transparent"> <div class="row mt-5"> <div class="col-2" *ngFor="let stat of statLookup"> <div class="{{stat.couleur}} mx-xxl-4 mx-2 mx-md-1 rounded-4"> <div class="fw-bold">{{stat.prefix}}<span class="d-none d-lg-inline">{{stat.suffix}}</span> </div> <div class="h2"> {{getModifier(myCharactere.statistics[stat.key])}} </div> <div> {{myCharactere.statistics[stat.key]}} </div> </div> </div> </div>
Service TypeScript代码
export class ServeurService { token = ''; serverCharacter = 'https://cegep.fdtt.space/v1/characters'; serverSecret = 'https://cegep.fdtt.space/v1/secret'; serverToken = 'https://cegep.fdtt.space/v1/token'; personnages: any[] = []; persoName = ''; constructor(private http_client: HttpClient) { } setPersonnageName(name: string) { this.persoName = name; } getPersonnageName():string { return this.persoName; } getPersonnageByName(name: string) { const persoSelectionne = this.getPersonnages().find((n: {name: string; }) => n.name === name); return persoSelectionne; } }
问题原因
- 初始化时机错误:组件属性
myCharactere在类初始化阶段就调用myService.getPersonnageByName(),此时Service中的personnages数组为空(初始值为空,且无数据加载逻辑),find方法找不到匹配项返回undefined,导致HTML访问myCharactere.statistics触发错误。 - Service方法缺失:
getPersonnageByName中调用的getPersonnages()方法未实现,也没有处理HTTP异步加载数据的逻辑,无法从后端获取人物数据。 - 异步数据未正确处理:即便后续加载数据,同步获取的方式也无法拿到异步返回结果,导致数据始终无法显示。
解决方案
1. 修复Service,添加异步数据加载逻辑
修改Service代码,实现getPersonnages()方法并缓存数据,同时将getPersonnageByName改为返回Observable:
import { Observable, of, tap, map } from 'rxjs'; export class ServeurService { token = ''; serverCharacter = 'https://cegep.fdtt.space/v1/characters'; serverSecret = 'https://cegep.fdtt.space/v1/secret'; serverToken = 'https://cegep.fdtt.space/v1/token'; personnages: any[] = []; persoName = ''; constructor(private http_client: HttpClient) { } setPersonnageName(name: string) { this.persoName = name; } getPersonnageName():string { return this.persoName; } // 获取人物列表,缓存已加载的数据 getPersonnages(): Observable<any[]> { if (this.personnages.length > 0) { return of(this.personnages); } return this.http_client.get<any[]>(this.serverCharacter).pipe( tap(data => this.personnages = data) ); } // 异步获取指定名称的人物 getPersonnageByName(name: string): Observable<any> { return this.getPersonnages().pipe( map(personnages => personnages.find(n => n.name === name)) ); } }
2. 修改组件,异步获取数据
将myCharactere的初始化移到ngOnInit中,通过订阅Observable获取异步数据:
export class StatsComponent implements OnInit { myCharactere: ICharactere | undefined; statLookup = [ { key: 'str', prefix: $localize`str`, suffix: $localize`enght`, couleur: 'bg-danger' }, { key: 'dex', prefix: $localize`dex`, suffix: $localize`terity`, couleur: 'bg-primary' }, { key: 'con', prefix: $localize`con`, suffix: $localize`stitution`, couleur: 'bg-warning' }, { key: 'int', prefix: $localize`int`, suffix: $localize`elligence`, couleur: 'bg-success' }, { key: 'sag', prefix: $localize`wis`, suffix: $localize`dom`, couleur: 'bg-info' }, { key: 'cha', prefix: $localize`cha`, suffix: $localize`risma`, couleur: 'bg-dark' } ]; constructor(public myService: ServeurService) { } ngOnInit(): void { this.myService.getPersonnageByName("Xefoul Snaromers").subscribe(perso => { this.myCharactere = perso; console.log("mon perso stats", this.myCharactere); }); } getModifier(stat: number): string { const mod = Math.floor((stat - 10) / 2); return mod < 0 ? `${mod}` : `+${mod}`; } }
3. 优化HTML,确保数据存在后再渲染
使用*ngIf判断myCharactere是否存在,避免空值访问:
<div class="row text-center text-light bg-secondary mt-2 bg-transparent" *ngIf="myCharactere"> <div class="row mt-5"> <div class="col-2" *ngFor="let stat of statLookup"> <div class="{{stat.couleur}} mx-xxl-4 mx-2 mx-md-1 rounded-4"> <div class="fw-bold">{{stat.prefix}}<span class="d-none d-lg-inline">{{stat.suffix}}</span> </div> <div class="h2"> {{getModifier(myCharactere.statistics[stat.key])}} </div> <div> {{myCharactere.statistics[stat.key]}} </div> </div> </div> </div>
内容的提问来源于stack exchange,提问作者p3terson
相关产品推荐
相关产品推荐

