Pure и Impure Pipes
Pipes бывают двух типов: pure (не допускающие изменений) и impure (допускающие изменений). Различие между этими двумя типами заключается в реагировании на изменение значений, которые передаются в pipe.
По умолчанию все pipes представляют тип "pure". Такие объекты отслеживают изменения в значениях примитивных типов (String, Number, Boolean, Symbol). В других объектах - типов Object, Array, Function, Date изменения отслеживаются, когда меняется ссылка, а не значение по ссылке. То есть, если в массив добавили элемент, массив поменялся, но ссылка переменной, которая представляет данный массив, не изменилась. Поэтому подобное изменение pure pipes не будут отслеживать.
Impure pipes отслеживают все изменения. Возможно, возникает вопрос, зачем тогда нужны pure pipes? Дело в том, что отслеживание изменений сказывается на производительности, и поэтому pure pipes могут показывать лучшую производительность. К тому же не всегда необходимо отслеживать изменения в сложных объектах, иногда это совершенно не нужно.
Для наглядности напишем join pipes. Он будет применяться к массиву строк и соединять элементы массива через запятую.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'join'
})
export class JoinPipe implements PipeTransform {
transform(array: any, start?: any, end?: any): any {
return array.join(", ");
}
}
Этот pipe производит операции над массивом. Соответственно если в компоненте динамически добавлять новые элементы в массив, к которому применяется JoinPipe, то мы не увидим изменений. Так как JoinPipe не будет отслеживать изменения над массивом.
Теперь сделаем его impure pipe. Для этого добавим в декоратор Pipe параметрpure: false
:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'join',
pure: false
})
export class JoinPipe implements PipeTransform {
transform(array: any, start?: any, end?: any): any {
return array.join(", ");
}
}
По умолчанию параметр pure равенtrue
.
Теперь мы можем добавлять в компоненте новые элементы в этот массив:
import { Component} from '@angular/core';
@Component({
selector: 'my-app',
template: `<input #phone name="phone" class="form-control">
<button class="btn" (click)="phones.push(phone.value)">Add</button>
<p>{{phones | join}}</p>`
})
export class AppComponent {
phones = ["iPhone 7", "LG G 5", "Honor 9", "Idol S4", "Nexus 6P"];
}
Когда добавляется новый элемент, класс JoinPipe заново начинает обрабатывать массив. Поэтому pipe применяется ко всем элементам.