如何仅在值更改时调用管道

时间:2017-07-30 04:33:07

标签: angular primeng angular-pipe

我正在使用带有primeng p-dropdown的angular 2,并且在用户选择父级时我需要过滤子下拉列表。我使用像

这样的自定义管道来做到这一点
<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,它会继续在控制台上非常快速地记录该消息(比如每100ms一次),这意味着即使父值没有改变它也会继续调用。这样做的副作用是,如果有滚动,我无法在子下拉列表中选择任何值,因为它会继续刷新选项。

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

enter image description here

P.S:我不想在onChange事件中执行它并从组件调用管道,所以可以在模板内部进行吗?

1 个答案:

答案 0 :(得分:0)

这种情况正在发生,因为管道不正确

  

纯管道:Angular仅在检测到输入值的纯粹更改时才执行纯管道。纯变化是对原始输入值(String,Number,Boolean,Symbol)的更改或更改的对象引用(Date,Array,Function,Object)。

     

不纯管道: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();
    ...
  }
  ...
}