我在Angular中动态添加的组件中的更改检测遇到问题。
我在下面添加了指向完整Plunker的链接。
该组件具有两个属性(网格和消息),两个属性都有设置器和获取器。
网格属性基于“类型”界面 IGrid ,而消息是字符串。 动态创建组件并将其添加到父组件时,网格和消息都会添加到组件实例。
网格和消息的设置者调用名为 consolelog 的函数。
根据各自输入的更改,网格和消息的更改检测似乎都可以正常工作。
我遇到的问题是在消息设置器中正确调用了 consolelog 函数,但是没有在 consolelog 函数中在网格设置器中正确调用了。
模板:
<div>
<div><b>grid.pinnedColumnHeaders</b></div>
input:
<input type="checkbox"
name="grid.pinnedColumnHeaders"
[(ngModel)]="grid.pinnedColumnHeaders">
</div>
<div>
value: {{ grid.pinnedColumnHeaders || '[blank]' }}
</div>
<hr>
<div>
<div><b>message:</b></div>
input: <input type="text" name="message"
[(ngModel)]="message">
</div>
<div>
value: {{ message || '[blank]' }}
</div>
组件:
@Component({
selector: 'app-change-detection-onpush',
template: `...`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChangeDetectionOnPushComponent implements IPage {
private _message: string;
private _grid: IGrid;
ngAfterViewInit() {
}
constructor(private cdRef: ChangeDetectorRef) { }
set grid(val: string) {
this.cdRef.markForCheck();
this.logconsole();
this._grid = val;
}
get grid() {
return this._grid;
}
set message(val: string) {
this.cdRef.markForCheck();
this.logconsole();
this._message = val;
}
get message() {
return this._message;
}
logconsole(){
console.log('test');
}
}
完整柱塞: https://next.plnkr.co/edit/t1xK698tsJDnzS5E?open=lib%2Fapp.ts&deferRun=1
答案 0 :(得分:1)
根据您在评论中所说,我对您可能要使用的方法还有两个猜测:
是将grid
设为私有Subject
(还是“ rxjs”的BehaviorSubject)
在您的服务中,并在服务中使设置者和获取者受益。
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable()
export class MyService{
private grid: Subject<IGrid> = new Subject<IGrid>();
getGrid(): Observable<IGrid> {
return this.grid.asObservable();
};
setGrid(values: IGrid): void {
this.grid.next(values);
}
}
然后在您的任何组件中使用(请注意,不要忘记在ngOnDestroy()上设置unsubscribe
)
export class MyComponent {
grid: IGrid;
constructor(private service: Myservice){}
getGrid(): void {
this.service.getGrid().subscribe((grid: IGrid) => this.grid = grid);
}
setGrid(gridData: IGrid): void {
this.service.setGrid(gridData);
}
}
仍然,在这种方法中,您必须按照上面的建议处理输入更改,因为如果仅对象的一部分发生了更改,ngModel不会调用setter。但是在这种情况下,您可以确定,如果在一个地方进行更改,则所有订阅者都会收到更改。