Angular и KeyValueDiffers для отслеживания изменений в объектах

Apr 2, 2018

У директив нет аналога для свойства pipe фильтров (pure: true, по умолчанию. pure: false говорит, что значение для pipe может меняться динамически), поэтому отслеживание изменений (например, служб) лежит полностью на самих директивах.

Директива может получать параметры через входное свойство (имя директивы).

Например, изменения в службе discount определяется при помощи службы KeyValueDiffers.

constructor(private keyValueDiffers: KeyValueDiffers,
            private discount: DiscountService) { }

Служба KeyValueDiffers работает с парами объектов 'ключ-значение' (например, Map) или с обычными объектами. Когда вызывается метод ngDoCheck директива использует диффер пары 'ключ-значение', чтобы узнать о наличии изменений.

Отметьте и метод ngOnChanges, который позволяет реагировать на изменение значения входящего свойства.

<div [price]="item.price"
    #discount="discount">
    {{ discount.discountAmount | currency:"USD": true }}
</div>
import { Directive, Input,
    SimpleChange, KeyValueDiffer, KeyValueDiffers } from "@angular/core";
import { DiscountService } from "./discount.service";

@Directive({
    selector: "[price]",
    exportAs: "discount"
})
export class PaDiscountAmountDirective {
    private differ: KeyValueDiffer<any, any>;

    constructor(private keyValueDiffers: KeyValueDiffers,
                private discount: DiscountService) { }

    @Input("price")
    initPrice: number;

    discountAmount: number;

    ngOnInit() {
        this.differ = this.keyValueDiffers.find(this.discount).create();
    }

    // когда меняется входящее значение
    ngOnChanges(changes: { [property: string]: SimpleChange }) {
        if (changes["initPrice"] != null) {
            this.updateValue();
        }
    }

    // проверяем наличие изменение свойства discount, определяемое классом/службой DiscountService
    ngDoCheck() {
        if (this.differ.diff(this.discount) != null) {
            this.updateValue();
        }
    }

    private updateValue() {
        this.discountAmount = this.initPrice - this.discount.applyDiscount(this.initPrice);
    }
}

Обратите внимание также как директива присваивается переменной шаблона, в результате чего мы имеем доступ к свойству директивы discountAmount.

Добавить комментарий