← Назад к вопросам

Когда срабатывает on changes?

2.3 Middle🔥 111 комментариев
#Soft Skills и рабочие процессы

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Механизм и моменты срабатывания ngOnChanges в Angular

ngOnChanges — это один из ключевых хуков жизненного цикла (Lifecycle Hooks) в Angular. Он срабатывает в строго определённых ситуациях, связанных с изменением входных свойств (@Input() декоратор) компонента или директивы. Понимание точных условий его вызова критически важно для эффективной отладки и проектирования реактивной логики.

Ключевые условия срабатывания

ngOnChanges вызывается автоматически фреймворком Angular в следующих случаях:

  1. Перед инициализацией ngOnInit (при первом присвоении): При самом первом установке значения входного свойства из родительского компонента. Важно: хук сработает, даже если значение было передано как undefined или null.
  2. При изменении ссылки на объект входного свойства: Когда родительский компонент повторно выполняет привязку к @Input()-свойству, и новое значение отличается от предыдущего по ссылке (reference inequality). Это фундаментальное условие.

Что НЕ вызовет ngOnChanges:

  • Изменение мутабельного объекта по ссылке: Если родитель передал объект или массив, и изменил его внутреннее состояние (например, добавил элемент в массив или изменил свойство объекта), но сама ссылка на этот объект осталась прежней, хук вызван не будет.
  • Изменение локальных свойств компонента: Хук реагирует только на свойства, помеченные декоратором @Input().
  • Изменения, инициированные внутри самого компонента.

Практический пример и анализ

Рассмотрим типичный сценарий с дочерним компонентом:

// child.component.ts
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `<p>{{ user.name }} ({{ user.age }} лет)</p>`
})
export class ChildComponent implements OnChanges {
  @Input() user: { name: string; age: number };
  @Input() title: string;

  ngOnChanges(changes: SimpleChanges) {
    console.log('Хук ngOnChanges вызван!');
    for (const propName in changes) {
          const change = changes[propName];
          console.log(`Свойство "${propName}":`, {
            previousValue: change.previousValue,
            currentValue: change.currentValue,
            firstChange: change.firstChange
          });
        }
  }
}
// parent.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    <app-child [user]="currentUser" [title]="pageTitle"></app-child>
    <button (click)="increaseAge()">Увеличить возраст</button>
    <button (click)="changeUser()">Заменить пользователя</button>
  `
})
export class ParentComponent {
  pageTitle = 'Профиль';
  currentUser = { name: 'Иван', age: 30 };

  increaseAge() {
    // МУТАЦИЯ: изменится свойство объекта, но ссылка останется прежней.
    this.currentUser.age++;
    // ngOnChanges в ChildComponent НЕ БУДЕТ ВЫЗВАН!
  }

  changeUser() {
    // ПЕРЕСОЗДАНИЕ: создаётся новый объект, ссылка меняется.
    this.currentUser = { ...this.currentUser, age: this.currentUser.age + 1 };
    // ngOnChanges в ChildComponent БУДЕТ ВЫЗВАН!
  }
}

Анализ поведения:

  • При первоначальной отрисовке ngOnChanges сработает дважды (для user и title), и у каждого свойства change.firstChange будет true.
  • Нажатие на "Увеличить возраст" не вызовет хук, так как изменяется содержимое существующего объекта.
  • Нажатие на "Заменить пользователя" вызовет хук, потому что мы создаём совершенно новый объект и передаём новую ссылку.

Объект SimpleChanges

Хук получает один аргумент типа SimpleChanges — это объект, ключами которого являются имена изменившихся входных свойств. Каждое значение — это экземпляр класса SimpleChange, содержащий:

  • previousValue: предыдущее значение.
  • currentValue: текущее (новое) значение.
  • firstChange: булево значение, указывающее, первое ли это изменение для данного свойства.

Стратегии работы и лучшие практики

  • Для реактивности на мутацию объектов используйте:
    *   **Observable-паттерн** с `async` pipe.
    *   **Геттер/сеттер** для входного свойства с дополнительной логикой внутри сеттера.
    *   Хук `ngDoCheck` для реализации кастомной логики обнаружения изменений (но с осторожностью, из-за высокой частоты вызова).
  • Логирование и отладка: ngOnChanges — идеальное место для отслеживания того, как и когда данные поступают извне.
  • Вычисление производных данных: Если некоторое состояние компонента должно обновляться строго в ответ на изменение входных данных, эту логику часто размещают в ngOnChanges, а не в ngOnInit или ngDoCheck.

Итог: ngOnChanges — это механизм Angular для реактивности на изменение ссылок входных свойств. Его срабатывание предсказуемо и обусловлено переприсвоением значения @Input()-свойству из шаблона родительского компонента. Для работы с мутабельными структурами данных требуется применение дополнительных паттернов, выходящих за рамки стандартного хука.

Когда срабатывает on changes? | PrepBro