Коллеги привет, искал себе решение как реагировать на изменения в объекте и нашел отличный сервис, который используется внутри директив таких как NgClass и NgStyle.
KeyValueDiffers позволяет создать KeyValueDiffer для сравнения изменений текущих пар ключ-значение с новыми. Если вы используете иммутабельные объекты, то можно просто обернуть все в эффект, ну а если вы наследники крутого легаси, где все объекты мутируются по ссылке, тогда проверку нужно вешать в DoCheck, чтобы реагировать на каждый тик change detection.
Накидал оба примера, чтобы поделиться с вами:
Иммутабельный с effect:
@Component({ selector: 'app-test', template: '' }) export class TestComponent { public state = input.required<Record<string, string | number>>(); private differs = inject(KeyValueDiffers); private differ: KeyValueDiffer<string, string | number> | undefined; constructor() { effect(() => { const currentState = this.state(); // создаем диффер, если он еще не создан if (!this.differ) { this.differ = this.differs.find(currentState).create(); } // Эффект будет перезапускаться при изменении инпут-сигнала. const changes = this.differ.diff(currentState); // только если есть изменения if (changes) { changes.forEachAddedItem((record) => { console.log(`В объект добавлена запись: Ключ: ${record.key} | Значение: ${record.currentValue}`) }); changes.forEachChangedItem((record) => { console.log(`Изменено: ${record.key} | Новое значение: ${record.currentValue}`) }); changes.forEachRemovedItem((record) => { console.log(`Удалено: ${record.key}`) }); // Остальные методы forEachItem и forEachPreviousItem по необходимости } }) } }
Легаси подход, которого, надеюсь, ни у кого нет, но на всякий случай :)
@Component({ selector: 'app-legacy', template: '' }) export class LegacyComponent implements OnInit, DoCheck { @Input({ required: true }) state!: Record<string, string | number>; private differs = inject(KeyValueDiffers); private differ: KeyValueDiffer<string, string | number> | undefined; ngOnInit() { // Создаем диффер при инициализации this.differ = this.differs.find(this.state).create(); } // Запускается на каждый тик change detection, так как мутации по-другому не отследим. ngDoCheck(): void { const changes = this.differ?.diff(this.state); if (changes) { changes.forEachAddedItem((record) => { console.log(`В объект добавлена запись: Ключ: ${record.key} | Значение: ${record.currentValue}`) }); changes.forEachChangedItem((record) => { console.log(`Значение изменилось: ${record.key}`) }); changes.forEachRemovedItem((record) => { console.log(`Запись удалена: ${record.key}`) }); // Остальные методы forEachItem и forEachPreviousItem по необходимости } } }











