没有`changeDetetectorRef.markForCheck`,为什么组件没有检测到内部状态变化?

时间:2017-10-17 22:05:31

标签: javascript angular zone.js

一般

我有问题。如果不调用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,我会没问题)我想在我的代码中发现错误。

希望你能在那里帮助我。

1 个答案:

答案 0 :(得分:1)

这是由于在父组件上添加了ChangeDetectionStrategy.OnPush。

在该父母中,如果他的输入的引用没有改变,则不会检查他的子树组件是否有变化。