【问题标题】:How to call pipe only on value change如何仅在值更改时调用管道
【发布时间】:2017-07-30 04:33:07
【问题描述】:

我将 angular 2 与primeng p-dropdown 一起使用,并且有一种情况,当用户选择父级时,我需要过滤子级下拉菜单。我是使用自定义管道完成的,例如

<p-dropdown [options]="carTypesOptions" [(ngModel)]="CarTypeId" name="CarTypeId"></p-dropdown>
<p-dropdown [options]="carMakeOptions | filterCarMakes: CarTypeId" [(ngModel)]="CarMakeId" name="CarMakeId"></p-dropdown>

因此,当用户选择汽车类型时,我会使用 filterCarMakes 管道过滤第二个下拉列表,该管道采用 CarTypeId(父选择的 id)。这一切都很好。这是我的filterCarMakes 管道。

@Pipe({
    name: 'filterCarMakes',
    pure: false
})
export class FilterMakesPipe implements PipeTransform {
    transform(carMakesOptions: CarMakeSelectItem[], carTypeId: string): CarMakeSelectItem[] {
        if (!carTypeId)
            return carMakesOptions.filter(p => p.carTypeId == null);
        //perform some filtering operation
        return filteredCarMakeOptions;
    }
}

问题是,如果我将 console.log 放在管道中,它会继续非常快速地在控制台上记录该消息(例如每 100 毫秒一次),这意味着即使 parent 的值没有改变,它也会继续调用.这样做的副作用是,如果有滚动,我无法在子下拉列表中选择任何值,因为它会继续刷新选项。

过滤下拉列表的简单截图如下(它不会让我滚动选择其他值并会继续刷新)

P.S:我不想在 onChange 事件中做它并从组件调用管道,那么可以在模板内做吗?

【问题讨论】:

  • 通过删除pure: false 使管道变得纯净,只有当输入值发生变化时,角度才会调用变换方法。另见stackoverflow.com/questions/39757603/…
  • @yurzui,早上好:D。这应该是答案
  • 谢谢@yurzui 它成功了!这使它成为一个愚蠢的问题,然后大声笑
  • Angular 团队不鼓励过滤管道,正是出于这些原因。
  • 在组件类中进行过滤。为过滤后的列表创建一个属性并绑定到该属性。然后当过滤条件改变时,重置过滤列表。如果你有兴趣,我有一个例子。 (但我的例子是基于输入框,而不是下拉)

标签: angular primeng angular-pipe


【解决方案1】:

发生这种情况是因为管道不纯

纯管道:Angular 仅在检测到输入值发生纯更改时才执行纯管道。纯粹的更改要么是对原始输入值(字符串、数字、布尔值、符号)的更改,要么是更改的对象引用(日期、数组、函数、对象)。

不纯管道:Angular 在每个组件更改检测周期中执行一个不纯管道。经常调用不纯管道,就像每次击键或鼠标移动一样频繁。

来源:https://angular.io/guide/pipes

但如果您出于任何原因确实需要管道不纯,出于性能考虑,您需要将组件 changeDetection 策略设置为OnPush,并在应用更改时手动触发更改检测。

import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';

@Component({
  selector: 'awesome-component',
  templateUrl: './pda.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class AwesomeComponent implements OnInit {
  constructor(
    private cd: ChangeDetectorRef,
  ) { }

  ...

  fetchData() {
    ...
    // after any data change
    this.cd.markForCheck();
    ...
  }
  ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 2020-11-02
    • 2019-02-11
    • 2021-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多