Angular Async Pipe没有订阅EventEmitter的初始值



使用Angular的ChangeDetectionStrategy.OnPush,我尽量使用Async-Pipe/订阅可观察对象,只要我可以-对吧?所以不像{{value}}那样绑定到我的值,我宁愿使用{{valueChange | async}},它工作得很好,除了初始值。我认为事件是在模板加载之前触发的,所以它没有得到初始值:

https://stackblitz.com/edit/angular-b9wbvu

解决这个问题的最佳实践是什么?还是我对ChangeDetectionStrategy.OnPush的理解有误?

正如上面@M1CH3L1US所提到的,这不是关于changeDetectionStrategy的问题。changeDetectionStrategy影响如何触发变更检测。对于这个线程中的各种changeDetectionStrategy有多种解释。

什么是ChangeDetectionStrategy在Angular2和何时使用OnPush Vs默认?

关于你的问题,有一些解决办法

  1. 使用一个不同的Angular生命周期钩子来触发你的初始值,比如AfterViewInit就可以了

export class AppComponent implements OnInit, AfterViewInit {
name = 'Angular';
setRandomValue(): void {
this.value = new Date().toString();
}
ngOnInit(): void {
}

ngAfterViewInit(){
this.setRandomValue();
}
@Input() set value(v: string) {
this._value = v;
this.valueChange.emit(this._value);
}
@Output() valueChange = new EventEmitter<string>();
public _value: string;
}

  1. 使用行为主题

这个方法将允许你的Observable实际存储一个值,防止任何竞争条件。

export class AppComponent implements OnInit, AfterViewInit {
name = 'Angular';
value$ = new BehaviorSubject(null);
setRandomValue(): void {
const newValue =  new Date().toString()
this.value$.next( newValue )
this.value = newValue
}
ngOnInit(): void {
this.setRandomValue();
}

ngAfterViewInit(){
}
@Input() set value(v: string) {
this._value = v;
this.valueChange.emit(this._value);
}
@Output() valueChange = new EventEmitter<string>();
public _value: string;
}

<hello name="{{ name }}"></hello>
<p>
Start editing to see some magic happen :)
</p>
<p>
Current Value non async: {{_value}}
</p>
<p>
Current Value: {{value$ | async}}
</p>
<p>
<button (click)="setRandomValue()">ChangeValue</button>
</p>
  1. 最后,你必须问自己是否需要异步值?如果这个值是通过@Input传入的,就像你的例子一样,你总是会得到传递给组件的实际值。因此,您可能不需要额外的复杂性

当你订阅EventEmitter(或者更确切地说,Angular通过async管道订阅它)的时候,ngOnInit中的代码已经运行了。EventEmitter扩展了一个不保存最近状态值的Subject。通过在第一个值已经发出之后订阅它,您将不会被第一个值通知。我建议你把启动代码移到ngAfterViewInit中,这将使初始化在视图被渲染后运行,并且事件发射器的订阅已经被Angular绑定了。

注:我只是注意到,改变ngAfterViewInit的值将不是最佳的,因为这将改变组件状态后,视图已被检查。为了确保你在保存端,我建议你在设置完组件状态后让Angular再次运行变更检测:

class AppComponent implements AfterViewInit {
constructor(private readonly cdRef: ChangeDetectorRef) {  }

ngAfterViewInit(): void {
this.setRandomValue();
this.cdRef.detectChanges();
}
}

ChangeDetectionStrategy在这里与它无关,因为Angular无法知道状态的变化。

希望这是有意义的:3

最新更新