Angular 计算信号的更新仅发生一次,但不适用于未来的依赖项更新

问题描述 投票:0回答:1

我正在尝试根据信号的值过滤数组,我认为计算信号是实现此目的的最佳选择。我的目标是仅显示与(通过自定义过滤功能)通过切换按钮在另一个组件中设置的相应反馈过滤器相匹配的结果。

父组件ts文件

export interface Data {
  name: string;
  total_fb: number;
  last30: number;
  trend: string;
}
 
...  

dataArray = [
    {name: 'Prod XY', total_fb: 4.5, last30: 3.6, trend: 'up'},
    {name: 'Prod lorem ipsum Z', total_fb: 4.2, last30: 3.3, trend: 'up'},
    {name: 'Prod VBG', total_fb: 3.3, last30: 3.7, trend: 'up'},
    {name: 'Prod XYZ', total_fb: 3.7, last30: 2.9, trend: 'down'},
    ...
];

filtersProd = signal({source: '1', feedback: 'all'});

filteredProdData = computed(() => {
    const rating = this.filtersProd().feedback;
    return this.dataArray.filter((el) => this.filterByFeedBackRating(el, rating));
});

filterByFeedBackRating = (data: Data, rating_value: string) => {
    if (rating_value === 'all') {
      return true;
    } else if (rating_value === '4+' && data.total_fb >= 4) {
      return true;
    } else if (rating_value === '3' && data.total_fb >= 3 && data.total_fb < 4) {
      return true;
    } else if (rating_value === '1/2' && data.total_fb < 3) {
      return true;
    }
    return false;
}

父组件模板

<div class="pre-content">
    <pre>source: {{filtersProd().source}} rating: {{filtersProd().feedback}}</pre>
    <app-filter-source-feedback [(filters)]="filtersProd"></app-filter-source-feedback>
</div>
<div class="content flex">
    <app-table-performance [data]="filteredProdData()"></app-table-performance>
</div>

FilterSourceFeedback组件ts文件

filters = model.required<{feedback: string|number, source: string}>();

FilterSourceFeedback 组件模板

<div class="toggle">
  <label>Feedback</label>
  <mat-button-toggle-group [(value)]="filters().feedback" hideSingleSelectionIndicator="true" name="feedback" aria-label="feedback rating">
    <mat-button-toggle value="all">all</mat-button-toggle>
    <mat-button-toggle value="4+">4+</mat-button-toggle>
    <mat-button-toggle value="3">3</mat-button-toggle>
    <mat-button-toggle value="1/2">1/2</mat-button-toggle>
  </mat-button-toggle-group>
</div>

TablePerformance组件ts文件

data = input<Data[]>([]);
dataSource = computed(() => new MatTableDataSource(this.data()));
columnsToDisplay = ['name', 'total_fb', 'last30', 'trend'];

TablePerformance 组件模板

<table mat-table [dataSource]="dataSource()">
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef> Name </th>
    <td mat-cell *matCellDef="let tourStat"> {{tourStat.name}} </td>
  </ng-container>
  <ng-container matColumnDef="total_fb">
    <th mat-header-cell *matHeaderCellDef> Total </th>
    <td mat-cell *matCellDef="let tourStat"> {{tourStat.total_fb}} </td>
  </ng-container>
  
  ...

  <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
  <tr mat-row *matRowDef="let row; columns: columnsToDisplay"></tr>
</table>

当我更改反馈切换按钮组的值时,父组件中的

filtersProd
信号与子组件中的模型信号
filters
完美同步。问题是计算信号
filteredProdData
返回的数组仅使用初始值进行过滤(如果我更改初始值,我会在表中获得正确的过滤结果),后续更新不会过滤初始数组,就好像计算信号不会“监听”其依赖项的更新。

自从我上次使用 Angular 的版本以来,信号功能还没有发布,但我不明白我哪里出了问题或者我错过了什么。

angular typescript angular-components angular-signals
1个回答
0
投票

您的代码不起作用的原因是因为默认情况下,Angular 信号使用引用相等来跟踪值是否已更改。您将对象存储在信号中,这意味着只要对象的引用相同,该值就被视为未更改。如果您只是在更新中更新属性,就像使用

[(value)]="filters().feedback"
进行绑定时所做的那样,则引用保持不变。 Angular 认为该值没有改变,因此不会发生重新计算。

要以干净的方式解决问题,您应该为过滤器的

source
feedback
提供单独的信号,而不是将它们都存储在一个对象中。您可以直接在信号上使用双向绑定(无需读取值),如下所示:

<mat-button-toggle-group [(value)]="filtersFeedback"> ...

按照我的建议,假设组件中有

filtersFeedback
信号。

© www.soinside.com 2019 - 2024. All rights reserved.