【问题标题】:Why ngFor with filter pipe cause infinite loop?为什么带有过滤器管道的ngFor会导致无限循环?
【发布时间】:2020-11-13 17:14:16
【问题描述】:

我有这种情况。 复选框组件


    <section
        *ngFor="let group of model.groups | myfilter:term; let index = index">
        <div>
            <mat-checkbox
                        [checked]="group.allChecked"
                        [ngModel]="group.allChecked"
                        color="primary">
                {{ group.name }}
            </mat-checkbox>
        </div>
        <div>
            <ul>
                <li *ngFor="let checkbox of groups.checkboxes;">
                    <mat-checkbox
                        [checked]="checkbox.check"
                        [(ngModel)]="checkbox.check"
                        color="primary">
                        {{ checkbox.displayName }}
                    </mat-checkbox>
                </li>
            </ul>
        </div>
    </section>


在我的第二个组件中

<mat-form-field
  appearance="outline">
  <mat-label>
    Search by
  </mat-label>
    <input
      matInput
      type="text"
      [(ngModel)]="filter">
    <mat-icon matPrefix fontIcon="icon-search"></mat-icon>
</mat-form-field>
    
<app-checkbox-group
   [datasource]="claims"
   [term]="filter"
>
</app-checkbox>

还有这个管道

@Pipe({
  name: 'roleFilter',
  pure: false
})
export class myfilter implements PipeTransform {

  transform(groups: [], term: string): [] {
    if (!term) {
      return groups;
    }
    return groups
            .map(obj => {
                  return Object.assign({}, obj, {
                    checkboxes: obj.checkboxes.filter(el => el.displayName.includes(term))
                  })
                
            })
            .filter(obj => obj.checkboxes.length > 0)
  }
}

而groups就是这样的数据集

[
    {
      name: 'Group 1',
      allChecked: false,
      isIndeterminate: false,
      checkboxes: [
        {
          check: true,
          displayName: 'first',
          name: 'first',
          id: '1',
          isMandatory: false
        },
        {
          check: false,
          displayName: 'second',
          name: 'second',
          id: '2',
          isMandatory: false
        },
        {
          check: false,
          displayName: 'third',
          name: 'third',
          id: '3',
          isMandatory: false
        },
        {
          check: false,
          displayName: 'fourth',
          name: 'fourth',
          id: '4',
          isMandatory: false
        },
        {
          check: false,
          displayName: 'fifth',
          name: 'fifth',
          id: '5',
          isMandatory: false
        },
        {
          check: false,
          displayName: 'sixth',
          name: 'sixth',
          id: '6',
          isMandatory: false
        },
        {
          check: false,
          displayName: 'seventh',
          name: 'seventh',
          id: '7',
          isMandatory: false
        },
        {
          check: false,
          displayName: 'eighth',
          name: 'eighth',
          id: '8',
          isMandatory: false
        },
      ]
    }
  ]

当我开始在输入过滤器上输入时,为了减少数据集,如果我开始输入与任何 displayName 不匹配的字母,则所有组都被隐藏并且它的工作方式与预期一样。 当我开始输入与复选框的某些 displayName 属性匹配的字母时,就会出现问题。 我不明白为什么,但是所有页面都冻结并且地图功能被无限次调用。

问题似乎出在 Object.assign 在 map 方法中。因为如果我改变这条线 obj.checkboxes = checkboxes: obj.checkboxes.filter(el =&gt; el.displayName.includes(term)) 可以,但是用过滤后的复选框替换原来的复选框。

【问题讨论】:

  • 嗨,你能指定 stackblitz 例子或类似的东西吗)
  • 尝试添加 trackByIndex(idx) {return idx;} 方法并将其传递给两个 ngFor insatnces 这样的*ngFor="let checkbox of groups.checkboxes; trackBy: trackByIndex"
  • @Andrei 谢谢!它使用trackBy工作。您能解释一下为什么只需添加 trackBy 即可?谢谢
  • trackBy 允许避免完全重新渲染元素。不确定到底是什么,但有些东西在渲染时调用了更改检测。我相信它是复选框上的 ngModel
  • 好的,谢谢!我怀疑同样的事情,但我错过了trackBy。非常感谢 :) 我会将您的评论注册为问题的答案,以将其标记为已解决。

标签: arrays angular typescript filter pipe


【解决方案1】:

根据@Andrei 的评论

尝试添加 trackByIndex(idx) {return idx;} 方法并将其传递给两个 ngFor 实例,例如 *ngFor="let checkbox of groups.checkboxes; trackBy: trackByIndex"

解决方案是在两个 *ngFor 指令上使用 trackBy 管道。

【讨论】:

    猜你喜欢
    • 2013-06-17
    • 1970-01-01
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-06
    • 1970-01-01
    相关资源
    最近更新 更多