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

Angular绑定ngrx store数据的selected属性时报只读错误如何解决?

问题原因

Ngrx Store 遵循单向数据流设计原则,所有通过 select 方法返回的状态对象默认是不可变的只读对象,会被冻结不允许直接修改。你用双向绑定 [(ngModel)] 直接修改从store取到的 language.selected 属性,本质是直接修改store内部状态,因此触发只读属性赋值报错。


解决方案

你可以根据业务需求选择以下两种方案:

  • 方案1:使用本地可变副本,不需要同步状态回Store
    拿到store返回的列表时,对每个对象做浅拷贝生成本地可变副本,后续双向绑定修改的是本地副本,不会触及store的只读对象。
    修改你的TS订阅代码即可:
    this.languagesSub = this.store.select(getCreateLanguagesLanguages).subscribe(res => {
      // 对每个language做浅拷贝,层级深的话可以用structuredClone做深拷贝
      this.languages = res.map(lang => ({...lang}))
    });
    
  • 方案2:遵循Ngrx数据流规范,状态变更同步回Store
    不用双向绑定,拆成单向绑定+事件派发Action的方式,所有状态变更都通过dispatch Action走Store的Reducer更新流程,符合Ngrx的设计规范。
    首先修改模板代码:
    <ul>
      <li *ngFor="let language of languages">
        <div>
          <mat-checkbox [ngModel]="language.selected" (ngModelChange)="handleLangSelect(language.id, $event)" color="primary">
            {{ language.value }}
          </mat-checkbox>
        </div>
      </li>
    </ul>
    
    然后在TS中新增事件处理方法,派发对应的更新Action到Store即可:
    handleLangSelect(langId: string, isSelected: boolean) {
      // 这里替换成你自己定义的更新语言选中状态的Action
      this.store.dispatch(updateLanguageSelected({ id: langId, selected: isSelected }))
    }
    
    这种方案不需要额外做对象拷贝,所有状态变更都在Store中统一处理,数据一致性更高。

内容的提问来源于stack exchange,提问作者Noah Bergh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 22:06:02