我有问题。如果不调用changeDetectorRef.markForCheck
方法,我的组件不会重新渲染。
我有自动填充功能。当输入更改时,我发送一些异步请求(只是简单的HttpClient服务和get
方法)。在那之后,我填写了一些内部状态。
注意markForCheck
电话。如果我删除这一行:没有任何作用。我注意到,如果我删除它,如果我点击组件外的某个地方,我会看到重新渲染。正确地点击某处组件时,会重新渲染组件。
顺便说一句,我意识到markForCheck
是偶然的。我只是尝试了一些东西而且很有效。我从一些文章中获得了有关CD机制和CD服务的信息。
这是我的主要内容:
@Component({
selector: 'tags-auto-complete',
template: `
<tags-internal-auto-complete-input
// ....
(inputChanged)="onInputChange($event);"
></tags-internal-auto-complete-input>
<tags-internal-auto-complete-results
[data]="queryResultsTags"
// ....
></tags-internal-auto-complete-results>
`,
})
export class TagsAutoCompleteContainerComponent implements OnInit {
inputChanged = new Subject<string>();
queryResultsTags: Tag[] = [];
constructor(
private tagsService: TagsService,
private changeDetectorRef: ChangeDetectorRef,
) {}
onInputChange(query: string): void {
this.inputChanged.next(query);
}
ngOnInit() {
this.inputChanged
.filter(inputValue => inputValue.length > 0)
.debounceTime(400)
.switchMap(query => this.tagsService.getTagsList({ query }))
.do(() => this.changeDetectorRef.markForCheck()); // note this
.subscribe((tags: Tag[]) => (this.queryResultsTags = tags)) // here I change the input of inner component
}
// ...
这是子组件(tags-internal-auto-complete-results
):
@Component({
selector: 'tags-internal-auto-complete-results',
template: `
<div class="container">
<span *ngFor="let tag of data" (click)="selectTag.emit(tag);" class="tag">
{{tag.name}}
</span>
</div>
`,
styleUrls: ['./results.styles.css'],
})
export class TagsAutoCompleteResultsComponent {
@Input() data: Tag[] = [];
@Output() selectTag = new EventEmitter<Tag>();
}
这些只是碎片。整个代码可以在GitHub上找到。
顺便说一句,我有另一个组件(选定的标签块),我输入了showLoader
。它有完全相同的问题。
可能问题以某种方式连接到区域机制。从我知道的一些文章中,zone.js monkey-patches一些事件或XHR调用。我的情况是XHR调用(我没有深入研究HttpClient,但它只能进行HTTP调用)。
我想了解为什么更改未检测到开箱即用(所以我将使用markForCheck,我会没问题)或我想在我的代码中发现错误。
希望你能在那里帮助我。
答案 0 :(得分:1)
这是由于在父组件上添加了ChangeDetectionStrategy.OnPush。
在该父母中,如果他的输入的引用没有改变,则不会检查他的子树组件是否有变化。