Angular 6中TypeError: Cannot read property 'className' of undefined错误排查
问题分析与解决方案
为什么会出现这个错误?
这个问题本质是异步数据加载和模板渲染的时机不匹配:你的hiveStrength、feedPriority、varroaCount变量是在异步请求的回调里才被赋值的,但Angular模板会在组件初始化完成后立刻开始渲染——这时候这些变量还处于undefined状态,模板尝试访问undefined.className就会抛出TypeError: Cannot read property 'className' of undefined。
虽然之后异步请求完成、变量被赋值后页面能正常显示,但初始化阶段的报错会一直留在控制台里。
几个可行的解决方案
方案1:使用可选链操作符(推荐,最简洁)
在模板中通过?.操作符安全访问属性,当变量为undefined或null时,表达式会直接返回undefined,不会触发报错:
<div class="row"> <div class="col-sm-4"> <small-stat [statClass]="hiveStrength?.className" [iconClass]="'fas fa-heart'" [label]="'Hive Strength'" [value]="hiveStrength?.name"> </small-stat> </div> <div class="col-sm-4"> <small-stat [statClass]="feedPriority?.className" [iconClass]="'fas fa-tint'" [label]="'Feed Priority'" [value]="feedPriority?.name"> </small-stat> </div> <div class="col-sm-4"> <small-stat [statClass]="varroaCount?.className" [iconClass]="'fas fa-bug'" [label]="'Varroa Count'" [value]="varroaCount?.name"> </small-stat> </div> </div>
方案2:用*ngIf控制渲染时机
通过*ngIf包裹整个需要渲染的区块,确保只有当所有数据都准备完成后才渲染模板:
<div class="row" *ngIf="hiveStrength && feedPriority && varroaCount"> <div class="col-sm-4"> <small-stat [statClass]="hiveStrength.className" [iconClass]="'fas fa-heart'" [label]="'Hive Strength'" [value]="hiveStrength.name"></small-stat> </div> <div class="col-sm-4"> <small-stat [statClass]="feedPriority.className" [iconClass]="'fas fa-tint'" [label]="'Feed Priority'" [value]="feedPriority.name"></small-stat> </div> <div class="col-sm-4"> <small-stat [statClass]="varroaCount.className" [iconClass]="'fas fa-bug'" [label]="'Varroa Count'" [value]="varroaCount.name"></small-stat> </div> </div>
方案3:初始化变量为默认空对象
在组件类中提前将这些变量初始化为空对象,避免它们一开始处于undefined状态:
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Params, Router } from '@angular/router'; import { InspectionService } from '@shared/services/inspection.service'; import { Inspection } from '@shared/models/inspection'; @Component({ selector: 'app-inspection-detail', templateUrl: './inspection-detail.component.html', styleUrls: ['./inspection-detail.component.scss'] }) export class InspectionDetailComponent implements OnInit { inspection: Inspection = new Inspection(); // 初始化空对象,避免undefined状态 hiveStrength: any = {}; feedPriority: any = {}; varroaCount: any = {}; constructor(private route: ActivatedRoute, private inspectionService: InspectionService, private router: Router) { } ngOnInit() { this.route.params.subscribe((params: Params) => { this.inspectionService.getInspection(params['id']).subscribe((response) => { this.inspection = response.data; this.hiveStrength = this.inspectionService.getHiveStrengthById(this.inspection.hive_strength); this.feedPriority = this.inspectionService.getFeedPriorityById(this.inspection.feed_priority); this.varroaCount = this.inspectionService.getVarroaCountById(this.inspection.varroa_count); console.log(this.hiveStrength); }); }); } }
补充说明
你看到控制台能正常打印目标对象,是因为console.log是在异步请求完成后执行的,这时候变量已经被赋值;但模板渲染是在组件初始化的更早阶段,那时候变量还没值,所以会触发报错。
内容的提问来源于stack exchange,提问作者Pedro
相关产品推荐
相关产品推荐

