为什么我需要使用默认的变更检测策略调用detectChanges()方法?

14 浏览
0 Comments

为什么我需要使用默认的变更检测策略调用detectChanges()方法?

我正在开发一个Angular 4应用程序,但是我遇到了一个问题,即当模型发生变化时,我需要调用this.changeDetectorRef.detectChanges();来更新视图。例如,我有这段代码用于分页:

changePage(pageNumber) {
  this.currentPage = pageNumber;
  // 为什么需要这样做?
  this.changeDetectorRef.detectChanges();
}

我已经在组件上明确设置了变更检测策略为ChangeDetectionStrategy.Default,但是这没有任何效果。当订阅一个可观察对象时,也会发生这种情况:

showResults(preference) {
  this.apiService.get('dining_autocomplete/', `?search=${preference}`)
    .subscribe((results) => {
      this.searchResults = results;
      // 为什么需要这样做?
      this.changeDetectorRef.detectChanges();
  });
}

如果我在TypeScript中console.log() this.searchResults,我会得到预期的结果,但是如果我在HTML中使用{{ searchResults }},它直到发生其他事件才会更新,可能是在进行另一个摘要周期时。

可能是什么原因呢?

== 编辑 ===========================================================

我的组件代码如下:

import {ChangeDetectorRef, Component, Input, OnChanges} from "@angular/core";
import * as _ from 'lodash';
@Component({
  selector: 'dining-search-results',
  templateUrl: './dining-search-results.template.html',
  styleUrls: ['./dining-search-results.style.scss'],
})
export class DiningSearchResultsComponent {
  @Input() searchResults: any[];
  @Input() hotTablesOnly: boolean = false;
  @Input() memberBenefitsOnly: boolean = false;
  numberOfTagsToDisplay: number = 3;
  resultsPerPage: number = 5;
  currentPage: number = 1;
  constructor(private changeDetectorRef: ChangeDetectorRef) {
  }
  get filteredResults() {
    return this.searchResults ?
      this.searchResults.filter((r) => !((this.hotTablesOnly && !r.has_hot_table)
        || (this.memberBenefitsOnly && !r.has_member_benefit))) : [];
  }
  get pagedResults() {
    return _.chain(this.filteredResults)
      .drop(this.resultsPerPage * (this.currentPage - 1))
      .take(this.resultsPerPage)
      .value();
  }
  get totalPages(): number {
    return Math.ceil(this.filteredResults.length / this.resultsPerPage);
  }
  getInitialTags(tagsArray: any[], count: number): any[] {
    return _.take(tagsArray, count);
  }
  changePage(pageNumber) {
    this.currentPage = pageNumber;
    // 为什么需要这样做?
    this.changeDetectorRef.detectChanges();
  }
}

当调用changePage()并更新this.currentPage时,如果不调用detectChanges(),HTML中的更改不会反映出来。

0
0 Comments

为什么我需要使用默认的变更检测策略调用detectChanges()?

在解决这个问题之前,我遇到了一个组件间的通信问题。另一个组件向该组件发送通知,但是在Angular区域之外运行Observable.fromEvent(),因此无法自动触发变更检测。在解决这个问题的过程中,我参考了关于zones的这篇文章和这个StackOverflow帖子上的解决方案。

在这个问题中,通过调用detectChanges()方法来手动触发变更检测是解决的办法。这个方法会强制Angular检查模型的变化并更新视图。在默认的变更检测策略下,Angular会自动调用detectChanges()方法,但是由于在Angular区域之外运行Observable.fromEvent(),导致变更检测无法自动触发。

通过调用detectChanges()方法,我们可以手动触发变更检测,并确保模型的变化能够及时反映到视图上。这样就可以解决视图不更新的问题。

需要注意的是,调用detectChanges()方法可能会增加应用程序的性能开销,因为它会触发整个组件树的变更检测。因此,我们应该谨慎使用这个方法,只在必要的情况下调用。

总结一下,当遇到组件间通信导致视图不更新的问题时,我们可以考虑使用默认的变更检测策略,并调用detectChanges()方法来手动触发变更检测。这样可以确保模型的变化能够及时反映到视图上,解决视图不更新的问题。同时,我们还应该注意谨慎使用detectChanges()方法,以避免不必要的性能开销。

0
0 Comments

为什么需要使用默认的变更检测策略时需要调用detectChanges()?

在上述代码中,我们将searchResults属性通过父组件的模板传递到子组件中,并在子组件的模板中使用它。当searchResults属性发生变化时,子组件会自动更新并显示新的值。

然而,问题出现在子组件中没有通过绑定方式绑定的属性上。例如,当页码发生变化时,视图并没有被更新。

这是因为ngOnChanges()方法只在与绑定结合使用时才起作用。在没有绑定的情况下,Angular的变更检测系统无法自动检测到属性的变化并更新视图。

解决这个问题的方法是手动调用detectChanges()方法来触发变更检测。在子组件中,我们可以在属性发生变化时调用detectChanges()方法来更新视图。

下面是解决方法的示例代码:

export class ChildComponent implements OnChanges {

@Input() searchResults;

constructor(private changeDetectorRef: ChangeDetectorRef) { }

ngOnChanges() {

// some code

// 手动调用detectChanges()方法来更新视图

this.changeDetectorRef.detectChanges();

}

}

通过调用detectChanges()方法,我们可以手动触发变更检测并更新视图。这样,即使没有通过绑定方式绑定的属性也能够在发生变化时更新视图。

总结起来,当我们需要在子组件中更新没有通过绑定方式绑定的属性时,需要手动调用detectChanges()方法来触发变更检测。这样可以确保视图能够正确地更新并显示最新的值。

0