Pure и Impure Pipes

Последнее обновление: 17.11.2023

Pipes бывают двух типов: pure (не допускающие изменений) и impure (допускающие изменений). Различие между этими двумя типами заключается в реагировании на изменение значений, которые передаются в pipe.

По умолчанию все pipes представляют тип "pure". Такие объекты отслеживают изменения в значениях примитивных типов (String, Number, Boolean, Symbol). В других объектах - типов Date, Array, Function, Object изменения отслеживаются, когда меняется ссылка, а не значение по ссылке. То есть, если в массив добавили элемент, массив поменялся, но ссылка переменной, которая представляет данный массив, не изменилась. Поэтому подобное изменение pure pipes не будут отслеживать.

Impure pipes отслеживают все изменения. Возможно, возникает вопрос, зачем тогда нужны pure pipes? Дело в том, что отслеживание изменений сказывается на производительности, и поэтому pure pipes могут показывать лучшую производительность. К тому же не всегда необходимо отслеживать изменения в сложных объектах, иногда это совершенно не нужно.

Теперь посмотрим на примере. В прошлой теме был создан класс FormatPipe:

import { Pipe, PipeTransform } from "@angular/core";
  
@Pipe({
    name: "format",
    standalone: true
})
export class FormatPipe implements PipeTransform {
  transform(value: number, args?: any): string {
      
    return value.toString().replace(".", ",");
  }
}

По умолчанию это pure pipe. А это значит, что он может отслеживать изменение значения, которое ему передается, так как оно представляет тип number.

В компоненте мы могли бы динамически изменять значение, для которого выполняется форматирование:

import { Component} from "@angular/core";
import {FormsModule} from "@angular/forms";
import { FormatPipe } from "./format.pipe";

@Component({
    selector: "my-app",
    standalone: true,
    imports: [FormsModule, FormatPipe],
    template: `<input [(ngModel)]="num" name="fact">
    <div>Результат: {{num | format}}</div>`
})
export class AppComponent { 
 
    num: number = 15.45;
}

Здесь никаких проблем с вводом бы не возникло - изменяем число в текстовом поле, и тут же изменяется форматируемый результат:

Pure Pipes in Angular 17

Но в прошлой теме был также создан другой pipe:

import { Pipe, PipeTransform } from "@angular/core";

@Pipe({
	name: "join",
    standalone: true
})
export class JoinPipe implements PipeTransform {
  transform(array: string[], start?: number|undefined, end?: number|undefined): any {
	let result = array;
	if(start){
		if(end){
			result = array.slice(start, end);
		}
		else{
			result = array.slice(start, result.length);
		}
	}
    return result.join(", ");
  }
}

Этот pipe производит операции над массивом. Соответственно если в компоненте динамически добавлять новые элементы в массив, к которому применяется JoinPipe, то мы не увидим изменений. Так как JoinPipe не будет отслеживать изменения над массивом.

Теперь сделаем его impure pipe. Для этого добавим в декоратор Pipe параметр pure: false:

import { Pipe, PipeTransform } from "@angular/core";

@Pipe({
	name: "join",
  standalone: true,
	pure: false
})
export class JoinPipe implements PipeTransform {
  transform(array: string[], start?: any, end?: any): string {
	  return array.join(", ");
  }
}

По умолчанию параметр pure равен true.

Теперь мы можем добавлять в компоненте новые элементы в этот массив:

import { Component} from "@angular/core";
import {FormsModule} from "@angular/forms";
import { JoinPipe } from "./join.pipe";

@Component({
    selector: "my-app",
    standalone: true,
    imports: [FormsModule, JoinPipe],
    template: `<input #user name="user">
               <button (click)="users.push(user.value)">Add</button>
               <p>{{users | join}}</p>`
})
export class AppComponent { 
 
    users = ["Tom", "Alice", "Sam", "Kate", "Bob"];
}

И ко всем добавленным элементам также будет применяться JoinPipe:

Impure Pipes in Angular 17

Когда добавляется новый элемент, класс JoinPipe заново начинает обрабатывать массив. Поэтому pipe применяется ко всем элементам.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850