Когда срабатывает on changes?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Механизм и моменты срабатывания ngOnChanges в Angular
ngOnChanges — это один из ключевых хуков жизненного цикла (Lifecycle Hooks) в Angular. Он срабатывает в строго определённых ситуациях, связанных с изменением входных свойств (@Input() декоратор) компонента или директивы. Понимание точных условий его вызова критически важно для эффективной отладки и проектирования реактивной логики.
Ключевые условия срабатывания
ngOnChanges вызывается автоматически фреймворком Angular в следующих случаях:
- Перед инициализацией
ngOnInit(при первом присвоении): При самом первом установке значения входного свойства из родительского компонента. Важно: хук сработает, даже если значение было передано какundefinedилиnull. - При изменении ссылки на объект входного свойства: Когда родительский компонент повторно выполняет привязку к
@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()-свойству из шаблона родительского компонента. Для работы с мутабельными структурами данных требуется применение дополнительных паттернов, выходящих за рамки стандартного хука.