如何访问JSON嵌套对象属性值并解决Angular嵌套ngFor渲染报错
问题修复方案
问题根因
- 方案1报错的核心原因是
Fragment模型中verses属性的类型定义错误,你定义的是单个Verse对象,但实际业务中一个片段对应多个经文,应该是Verse[]数组类型,*ngFor只能遍历可迭代的集合,不能遍历单个对象。 - 方案2报错是因为你在同步代码中直接操作未初始化的
fragments、verses变量,且逻辑混乱,异步请求返回前这两个变量都是undefined,自然会报属性缺失错误。
修复步骤
1. 修正Fragment模型类型定义
修改fragments.ts中的verses属性类型,同时补充嵌套经文的反序列化逻辑:
import {Deserializable} from './deserializable'; import { Chapter } from './chapter'; import { Verse } from './verse'; export class Fragment implements Deserializable { public id?: number; public url?: string; public surtitle?: string; public title_string?: string; public title_format?: number; public verses?: Verse[]; // 把原来的Verse改为Verse[] public chapter_id?: Chapter; deserialize(input: any): this { Object.assign(this, input); // 对嵌套的经文列表做实例化反序列化 if (input.verses) { this.verses = input.verses.map(verseItem => new Verse().deserialize(verseItem)); } return this; } }
2. 修正组件逻辑
删除ngOnInit中多余的同步map处理代码,直接使用Observable配合async管道即可,不需要手动维护本地变量,避免异步时序问题:
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs'; import {map} from 'rxjs/operators'; import { Fragment } from '../models/fragment'; import {ResponseApi} from '../models/api'; import { FragmentService } from '../services/fragment.service'; @Component({ selector: 'app-livre-detail', templateUrl: './livre-detail.component.html', styleUrls: ['./livre-detail.component.scss'] }) export class LivreDetailComponent implements OnInit { fragments$!: Observable<Fragment[]>; constructor( private route: ActivatedRoute, private fragmentService: FragmentService, ) { } ngOnInit() { const routeParams = this.route.snapshot.paramMap; const bookDiminutiveFromRoute = String(routeParams.get('bookDiminutive')); this.fragments$ = this.fragmentService.filterList( 'chapter_id__book_id__diminutive', bookDiminutiveFromRoute).pipe( map((responseApi: ResponseApi<Fragment>) => { // 对返回的每个片段做反序列化实例化 return responseApi.results.map(fragmentItem => new Fragment().deserialize(fragmentItem)); }) ); } }
3. 修正模板代码
配合async管道遍历,同时添加空值保护避免属性为空时报错:
<div *ngFor= 'let fragment of fragments$ | async'> <h3>{{ fragment.title_string }}</h3> <div> <!-- ?? [] 做空值兜底,经文列表为空时不会触发遍历错误 --> <div *ngFor= 'let verse of fragment.verses ?? []'> <span>{{ verse.number }}. </span> <span>{{ verse.text }}</span> </div> </div>
内容的提问来源于stack exchange,提问作者Vardane
相关产品推荐
相关产品推荐

