Angular中使用[value]为何无法通过async pipe更新select值?
问题描述
当$currentValue Observable发出新值时,使用[value]无法更新select元素的选中值,但使用[ngModel]="currentValue.value?.id"可正常工作。同时{{currentValue.value | json }}能正常更新,已尝试手动订阅赋值,也确认Observable会发出新值,想了解该现象的原因。
相关代码
select.component.html
<ng-container *ngIf="{value: $currentValues | async} as currentValues"> <ng-container *ngIf="{value: $currentValue | async} as currentValue"> {{currentValue.value | json }} <br> <select [value]="currentValue.value?.id" (change)="onZyklusChange($event)"> <option *ngFor="let zyklus of currentValues.value" [value]="zyklus.id"> {{zyklus.id}} {{zyklus.name}} </option> </select> </ng-container> </ng-container>
select.component.ts
$currentValues: Observable<IZyklus[]>; $currentValue: Observable<IZyklus>; constructor(private service: ZyklusService) { this.$currentValues = service.getAccessibleZyklen(); this.$currentValue = service.getCurrentElement(); }
IZyklus接口
export interface IZyklus { id: number, name: string, userLoggedIn: boolean }
问题原因分析
[value]与ngModel的更新逻辑差异[value]是普通单向绑定,仅当绑定表达式的引用关系发生变化时才会触发更新。你通过*ngIf="{value: $currentValue | async} as currentValue"生成的currentValue是每次Observable发新值时的全新对象,虽然currentValue.value?.id的数值可能没变,但Angular的变更检测机制有时不会主动重新计算这个表达式来同步select的选中值。ngModel属于表单控件绑定,Angular表单模块会主动监听绑定值的变化,不管上下文对象是否为新引用,都会强制同步控件的选中状态,所以能正常更新。
async管道与局部上下文的影响
- 你用
*ngIf创建的currentValue是局部上下文对象,每次$currentValue发新值都会生成新对象。插值表达式{{currentValue.value | json}}会强制触发重新渲染,所以能显示最新值,但[value]绑定的表达式可能没被Angular的变更检测机制标记为需要更新——如果组件使用了ChangeDetectionStrategy.OnPush策略,这种情况会更明显。
- 你用
手动订阅的细节问题
就算你手动订阅$currentValue并赋值给组件属性,如果没手动触发变更检测(比如调用this.changeDetectorRef.markForCheck()),在OnPush模式下[value]依然不会更新,但ngModel不受这个限制,因为表单控件内部会自行处理值同步。
内容的提问来源于stack exchange,提问作者BlueBlood
相关产品推荐
相关产品推荐

