You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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; 
  }
}

问题原因

  1. 初始化时机错误:组件属性myCharactere在类初始化阶段就调用myService.getPersonnageByName(),此时Service中的personnages数组为空(初始值为空,且无数据加载逻辑),find方法找不到匹配项返回undefined,导致HTML访问myCharactere.statistics触发错误。
  2. Service方法缺失:getPersonnageByName中调用的getPersonnages()方法未实现,也没有处理HTTP异步加载数据的逻辑,无法从后端获取人物数据。
  3. 异步数据未正确处理:即便后续加载数据,同步获取的方式也无法拿到异步返回结果,导致数据始终无法显示。

解决方案

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 00:25:54