我正在写一个简单的counter
。它在start,stop, toggle
中具有parent (app
功能,并使用child (counter) component
在ChangeDetectionStrategy.OnPush
中显示更改的值。
我面临的问题是在加载时子组件中无法显示initial counter value
。
下面是屏幕截图和代码。
app.component.ts
import { Component } from '@angular/core';
import {BehaviorSubject} from 'rxjs';
@Component({
selector: 'app-root',
template: `<h1>Change Detection</h1>
<button (click)="start()">Start</button>
<button (click)="stop()">Stop</button>
<button (click)="toggleCD()">Toggle CD</button>
<hr>
<counter [data]="data$" [notifier]="notifier$"></counter>`,
})
export class AppComponent {
_counter = 0;
_interval;
_cdEnabled = false;
data$ = new BehaviorSubject({counter: 0});
notifier$ = new BehaviorSubject(false);
start() {
if (!this._interval) {
this._interval = setInterval((() => {
this.data$.next({counter: ++this._counter});
}), 10);
}
}
stop() {
clearInterval(this._interval);
this._interval = null;
}
toggleCD(){
this._cdEnabled = !this._cdEnabled;
this.notifier$.next(this._cdEnabled);
}
}
counter.component.ts
import {Component, Input, ChangeDetectionStrategy, OnInit, ChangeDetectorRef} from '@angular/core';
import {Observable} from 'rxjs/index';
@Component({
selector: 'counter',
template: `Items: {{_data.counter}}`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CounterComponent implements OnInit {
@Input() data: Observable<any>;
@Input() notifier: Observable<boolean>;
_data: any;
constructor(private cd: ChangeDetectorRef) {}
ngOnInit() {
this.data.subscribe((value) => {
/**
Below this._data.counter is showing 0 in console.log but
not in template
**/
this._data = value;
this.cd.markForCheck();
});
this.cd.detach();
this.notifier.subscribe((value) => {
if (value) {
this.cd.reattach();
} else {
this.cd.detach();
}
});
}
}
我正在使用Angular 6.1.0
答案 0 :(得分:1)
您的AppComponent data$
是一个BehaviorSubject,您已为其指定了初始值。您的CounterComponent data
需要您订阅的Observable。默认的BehaviorSubject在更改之前不会触发。要获取值,您必须在加载时查询它:
@Input() data: BehaviorSubject<any>;
ngOnInit() {
this._data = this.data.value; // get the initial value from the subject
this.data.subscribe((value) => {
this._data = value;
this.cd.markForCheck();
}
);
应该可以解决问题。