Angular中赋值只读属性salaries触发TypeError的解决方案咨询
解决Angular中"Cannot assign to read only property 'salaries'"错误
问题原因
你遇到的错误是因为@Input()传入的profile对象是只读/不可变的(比如来自NgRx等状态管理库的冻结对象,或API返回时被设置为不可写的对象),直接修改它的属性会触发只读限制。你之前尝试的Object.defineProperty用法错误,因为你给salaries数组本身添加属性,而不是修改profile对象上salaries属性的可写性。
解决方案
1. 使用本地副本存储profile(推荐)
在组件内创建一个本地变量存储profile的拷贝,避免直接修改传入的只读对象:
export class ProfileFormComponent implements OnInit, OnDestroy { private _profile: ProfileModel; // 通过setter接收Input并创建副本 @Input() set profile(value: ProfileModel) { // 浅拷贝对象和数组,解除与原对象的引用 this._profile = { ...value, salaries: [...(value.salaries || [])] }; } // 提供getter供模板使用 get profile(): ProfileModel { return this._profile; } addSalary() { const salary: SalaryModel = { clientId: 1, profileId: this.profile.id, amount: this.salary.value, startDate: new Date(), endDate: null, }; // 优化嵌套订阅:用switchMap合并请求 this.apiService.profileService.addSalary(salary).pipe( switchMap(() => this.apiService.profileService.getProfile(this.profile.id)) ).subscribe(pc => { // 修改本地副本的salaries this._profile.salaries = [...pc.salaries]; this.resetDataForm(); }); } }
模板无需修改,依然使用profile.salaries即可。
2. 临时修改属性可写性(不推荐)
如果必须直接修改传入的profile对象,可以调整Object.defineProperty的目标:
this.apiService.profileService.getProfile(this.profile.id).subscribe(pc=>{ // 修改profile对象上salaries属性的可写性 Object.defineProperty(this.profile, 'salaries', { writable: true }); this.profile.salaries = [...pc.salaries]; this.resetDataForm(); });
这种方式不推荐,因为它破坏了原对象的不可变性设计,可能引发其他潜在问题。
3. 替换整个profile对象
如果父组件允许接收更新后的profile,可以通过@Output通知父组件更新:
export class ProfileFormComponent implements OnInit, OnDestroy { @Input() profile: ProfileModel; @Output() profileChange = new EventEmitter<ProfileModel>(); addSalary() { // ... 省略salary创建代码 this.apiService.profileService.addSalary(salary).pipe( switchMap(() => this.apiService.profileService.getProfile(this.profile.id)) ).subscribe(pc => { // 发送新对象给父组件 this.profileChange.emit(pc); this.resetDataForm(); }); } }
父组件使用时:
<app-profile-form [(profile)]="parentProfile"></app-profile-form>
内容的提问来源于stack exchange,提问作者Jesus
相关产品推荐
相关产品推荐

