Angular中TypeScript模型day属性WebApi映射后消失问题排查
问题分析与解决方案
你遇到的问题核心在于:response.json()返回的是普通JavaScript对象,而不是Activity类的实例。TypeScript的类型标注只是编译时的提示,运行时并不会自动把JSON对象转换成类的实例,所以类中定义的day属性的初始化逻辑根本没机会执行——自然就看不到这个属性了。
解决思路:手动实例化类并映射属性
要让day属性正常计算,你需要手动把JSON对象的属性赋值给Activity类的实例,这样类的初始化逻辑(或者构造函数)才会运行,计算出day的值。
方案1:在服务中直接映射实例化
修改你的服务请求方法,在map操作符里手动创建Activity实例并赋值:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { Activity } from './activity.model'; @Injectable() export class ActivityService { constructor(private http: HttpClient) {} getActivities(): Observable<Activity[]> { return this.http.get('/api/activities').pipe( map((activityJsons: any[]) => { return activityJsons.map(json => { const activity = new Activity(); activity.id = json.id; activity.activityDate = json.activityDate; // 此时day会通过类的初始化逻辑自动计算 return activity; }); }) ); } }
方案2:给类添加静态工厂方法(更优雅)
给Activity类添加一个静态方法,专门用来从JSON对象创建实例,这样代码更复用:
import * as moment from 'moment'; export class Activity { public id: number; public activityDate: string; public day: number; constructor(id?: number, activityDate?: string) { this.id = id; this.activityDate = activityDate; // 把day的计算移到构造函数里,确保赋值activityDate后能正确计算 this.day = activityDate ? moment(activityDate).dayOfYear() : 0; } // 静态工厂方法:从JSON对象生成Activity实例 static fromJson(json: { id: number; activityDate: string }): Activity { return new Activity(json.id, json.activityDate); } }
然后在服务里就可以简化成:
getActivities(): Observable<Activity[]> { return this.http.get('/api/activities').pipe( map((activityJsons: any[]) => activityJsons.map(Activity.fromJson)) ); }
额外提示
你原来的类中day的初始化写法有个小问题:moment(this.activityDate)在类初始化时,activityDate还没有被赋值(因为JSON映射是之后的事),所以原来的day其实会是moment(undefined).dayOfYear(),结果是0。把计算逻辑移到构造函数里,或者确保activityDate赋值后再计算day,才能得到正确的结果。
内容的提问来源于stack exchange,提问作者User.Anonymous
相关产品推荐
相关产品推荐

