为什么我需要标记检查? angular

Why do I need mark for check ? angular

我正在使用 angular 10, cdktable 我遇到了以下问题。

当我在 table 上执行搜索时,我的分页不会更新,除非我点击应用程序中的任何地方(它神奇地更新)...

这是一个变化检测问题,我的应用正在使用 onPush 策略。

现在,我的 table 正在从这个 observable

获取数据
connect(): Observable < Advertisers_advertisers_rows[] > {
  return this.store.pipe(
    select(advertiserPage),
    map((res) => {
      this.itemTotal = res.data.records
      this.page = res.data.page
      return res?.data?.rows || []
    })
  )
}

请注意,我在这里更新了项目总数和页面。

现在,这被传递给 table 组件

table.component.ts

<app-table
  [dataSource]="this"
  [pagination]="paginationOptions"
  (pageChange)="loadPage($event)"
  [itemTotal]="itemTotal"
></app-table>

自称分页

pagination.ts:

<app-table-pagination
  *ngIf="pagination"
  [options]="pagination"
  [(page)]="page"
  (pageChange)="pageChange.emit($event)"
  [total]="itemTotal"
></app-table-pagination>

如果我按照逻辑,itemTotal 更改,它将作为输入传递给 tablepagination,因此它应该触发更改。

如果我这样做,一切正常

connect(): Observable < Advertisers_advertisers_rows[] > {
  return this.store.pipe(
    select(advertiserPage),
    map((res) => {
      this.itemTotal = res.data.records
      this.page = res.data.page
      this.changeDetection.markForCheck()
      return res?.data?.rows || []
    })
  )
}

但我不明白为什么有这个必要。

当你使用 OnPush 策略时,你需要使用 markForCheck() 方法来说明 Angular 视图已更改并且应更新视图。

As Angular docs says:

When a view uses the OnPush (checkOnce) change detection strategy, explicitly marks the view as changed so that it can be checked again.

和:

Components are normally marked as dirty (in need of rerendering) when inputs have changed or events have fired in the view. Call this method to ensure that a component is checked even if these triggers have not occured.

更新:

itemTotal 未更新,因为 Angular 未获悉此更改。 我们如何告知?我们需要标记从组件到根的路径,以便为下一次更改检测进行检查 运行:

this.itemTotal = res.data.records
this.page = res.data.page
this.changeDetection.markForCheck()

You can read more here.

你的组件的 ChangeDetectionStrategy 是 OnPush 这意味着 仅当 @inputs 的引用时,更改检测才会 运行 已完全替换为新值。

例如:

var obj = {
    test:'test'
};

如果将 obj 值更新为

obj.test = 'new'

angular不会运行上述情况下的变化检测,因为引用 对象是相同的。因此,视图将不会更新。要更新视图, 我们需要手动告诉 angular 到 运行 变化检测。

为此,请使用 markForCheck 或 detectchanges。

在您的例子中,尽管 itemTotal 和 page 都更新了新值,但它指向相同的引用。 要更新视图,需要 markForCheck。