0

TL;DR:我已经有了可行的解决方案,但我想解释一下为什么 mat-select 会这样。

在使用 Angular Material 构建应用程序时,我在模板中mat-select结合使用时遇到了这个错误:函数被连续调用,就像在无限循环中一样,浏览器冻结。*ngForget priorities

零件

get priorities() {
    return [
        { name: 'NORMAL', value: 100 },
        { name: 'HIGH', value: 200 },
        { name: 'FORCE', value: 300 },
    ];
}
<mat-form-field appearance="outline">
  <mat-label>Priority</mat-label>
  <mat-select formControlName="priority">
    <mat-option *ngFor="let element of priorities" [value]="element"
      >{{ element.name }}</mat-option
    >
  </mat-select>
</mat-form-field>

可能的解决方案

  1. 指定每个 mat 选项(不带 ngFor)。尽管这在很多情况下都没有用。
<mat-form-field appearance="outline">
  <mat-label>Priority</mat-label>
  <mat-select formControlName="priority">
    <mat-option [value]="priorities[0]">{{ priorities[0].name }}</mat-option>
    <mat-option [value]="priorities[1]">{{ priorities[1].name }}</mat-option>
    <mat-option [value]="priorities[2]">{{ priorities[2].name }}</mat-option>
  </mat-select>
</mat-form-field>
  1. 使用原生 html 选择和选项。这是一个有效的解决方案,但我想让它与 Material 一起使用。
<select matNativeControl>
  <option *ngFor="let element of priorities" [value]="element">
    {{ element.name }}
  </option>
</select>
  1. 似乎为了使用mat-optionwithngFor我们需要添加一个trackBy函数。¿ 有人能解释一下为什么吗?我知道使用trackby可以提高效率,但我没有找到任何有关为什么必须将其与mat-select.
<mat-form-field appearance="outline">
  <mat-label>Priority</mat-label>
  <mat-select formControlName="priority">
    <mat-option
      *ngFor="let element of priorities; trackBy: prioritiesTrackByFn"
      [value]="element"
      >{{ element.name }}</mat-option
    >
  </mat-select>
</mat-form-field>
prioritiesTrackByFn(index, item): number {
    return item.value;
}
4

3 回答 3

1

这就是 Angular 变化检测的工作原理,它与 Angular 材质无关。例如,当您单击页面时,当您在输入中键入内容时,Angular 可以运行更改检测。Angular 不需要知道发生了什么变化,所以它会检查所有内容,包括你的 getter。并且当你的 getter 被调用时,数组的整个引用被改变(每次调用 getter 时你都返回一个新数组),你的数组被重新渲染,然后 Angular 检测到数组发生了变化,它将再次运行更改检测。 ......所以它有点变成了一个“循环”,即使它在技术上不是一个无限循环。作为一个*ngFor,它只会变得更糟。

关于角度变化检测,这值得一读:https ://blog.angular-university.io/how-does-angular-2-change-detection-really-work/

这里的简单解决方案是将数组分配给一个变量并在模板中迭代该数组,而不是使用 getter。

于 2021-10-20T17:31:10.043 回答
1

trackBy 用于检测项目的变化,而不是重绘所有项目

trackBy hepl 仅更新 1 个项目,没有 trackBy 角度将重绘所有项目(如果 var 是对象数组)

于 2021-10-20T11:23:07.163 回答
0

为什么要使用吸气剂?您是否尝试将优先级分配给 .ts 文件中的公共变量?

当然也可以使用 trackBy:function,如下所述:如何使用 `trackBy` 和 `ngFor`

喜欢:

export class xy {
  prios: PrioType[];

  constructor() {
    this.prios = getPrios();
  }

  trackById(index, item) {
    return item.id;
  } 
}
<map-option *ngFor="let element of prios; trackBy:trackById">{{element.name}}</mat-option>

于 2021-10-20T11:23:17.300 回答