4

我花了大约 3 天的时间试图弄清楚这一点。

预期行为:材料表始终使用来自后端的最新数据进行渲染。当从单独的组件将新项目添加到表中时,重定向到页面的路由器会显示更新的数据。

实际行为:第一次导航到页面时,表格为空。呈现了表,呈现了列标题,但没有填充行。导航离开然后返回正确填充表格。向表中添加新项目时,服务会将项目发送到后端,然后调用所有项目。然后该服务更新存储(另一个服务)。在重定向到表格组件时,表格似乎快速刷新旧数据,然后再次显示为空白。一旦我离开并返回,表格就会正确加载。

我正在使用下面的异步管道和服务。这对我来说似乎不正确......此外,ngOnChanges 没有记录任何内容。

appStore.service.ts

private _pets: ReplaySubject<Pet[]> = new ReplaySubject(1);
public readonly pets: Observable<Pet[]> = this._pets.asObservable();
getPets(): Observable<Pet[]> {
    return this.pets;
}

appDispatch.service.ts

public getPets(): Observable<Pet[]> {
    return this.appStore.getPets();
}

private setPets(pets: Pet[]) {
    this.appStore.setPets(pets);
}

petTableComponent.component.ts

...
changeDetection: ChangeDetectionStrategy.OnPush

constructor(private appDispatch: AppDispatchService,
              private router: Router) {
}

ngOnChanges(changes: SimpleChanges): void {
    console.log(changes.value.currentValue);
}

petTableComponent.component.html

<table
  mat-table
  [dataSource]="appDispatch.getPets() | async" multiTemplateDataRows
  class="mat-elevation-z8">

    <ng-container matColumnDef="name">
      <th mat-header-cell *matHeaderCellDef scope="col" [attr.role]="null"> <h4>Name</h4></th>
      <td mat-cell *matCellDef="let element" scope="row" [attr.role]="null">
        <p>{{element.pet.name}}</p>
      </td>
    </ng-container>
    ...

编辑 我尝试根据请求更改以下内容,结果与以前完全相同。

//changeDetection: ChangeDetectionStrategy.OnPush

宠物表.component.ts

constructor(private appDispatch: AppDispatchService,
              private router: Router,
              private cdr: ChangeDetectorRef) {
  }

  ngOnChanges(changes: SimpleChanges): void {
    console.log(changes.value.currentValue());
  }

  ngOnInit(): void {
    this.subscription = this.appDispatch.getReleaseItems()
      .subscribe(value => {
        this.data = value;
        this.cdr.detectChanges();
      });
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }

我将数据源更改为[dataSource]="data"

没有把握...

4

3 回答 3

0

您正在为您的数据使用 ReplaySubject ,它将“重播”所有下一个数据,但似乎不是初始化的数据new ReplaySubject(1)。如果您想使用数据初始化主题,并且只将最后一个最佳集合传递给订阅者(而不是像重播主题那样输出多个结果),请使用 BehaviorSubject

https://www.learnrxjs.io/learn-rxjs/subjects/replaysubject

于 2021-08-18T02:13:16.140 回答
0

这是因为您设置ChangeDetectionStrategy.OnPush了这意味着您的组件认为您仅依赖于您的@input属性,因此仅当这些值发生更改或从组件或其子级引发 DOM 对象事件时才会进行更改检测。

看看这篇文章,它有一个很好的例子解释:https ://netbasal.com/a-comprehensive-guide-to-angular-onpush-change-detection-strategy-5bac493074a4

您还可以手动运行更改检测:

constructor(private cdr: ChangeDetectorRef, private appDispatch: AppDispatchService) {
  ......
  this.appDispatch.Pets.subscribe(() => {
    this.cdr.detectChanges();  
  })
  

}

于 2020-01-07T16:20:45.030 回答
-1

尝试将 observable 存储在组件中

pets$: Observable<Pet[]> = this.appDispatch.getPets();

<table
  mat-table
  [dataSource]="pets$ | async" multiTemplateDataRows
  class="mat-elevation-z8">
于 2020-01-07T17:12:27.607 回答