Модуль 3 · урок 5 з 11
Сигнали і CD
Сигнали ти вже знаєш із модуля 2 як зручний спосіб тримати стан. Тут подивимось на них з іншого боку: як вони змінюють саму механіку перевірки й чому Angular рухається в цей бік.
Різниця в одному реченні
OnPush звужує перевірку до компонента: не змінився input — гілку пропускаємо.
Сигнали звужують її до конкретного місця в шаблоні: змінився сигнал — оновлюється рівно
той шматок розмітки, який його читав.
Що це змінює в коді
// було: поле + ручне повідомлення
export class TaskList {
tasks: Task[] = [];
private cdr = inject(ChangeDetectorRef);
load(): void {
this.api.getTasks().subscribe(t => {
this.tasks = t;
this.cdr.markForCheck();
});
}
}
// стало: сигнал
export class TaskList {
readonly tasks = signal<Task[]>([]);
load(): void {
this.api.getTasks().subscribe(t => this.tasks.set(t));
}
}
Зникає не лише рядок із markForCheck, а цілий клас помилок: «я оновив дані,
а екран не змінився». Angular дізнається про зміну від самого сигналу.
Сигнальні inputs і OnPush
export class TaskCard {
task = input.required<Task>();
readonly isLate = computed(() => new Date(this.task().dueDate) < new Date());
}
Тут computed робить те, для чого раніше писали ngOnChanges:
перераховується сам, коли прийшов новий task. І, що важливо, лише коли
прийшов новий — а не на кожній перевірці, як було б із методом у шаблоні.
Правило про незмінність нікуди не зникло
const tasks = signal<Task[]>([]);
tasks().push(item); // ❌ те саме посилання → нічого не станеться
tasks.update(list => [...list, item]); // ✅
Сигнал порівнює значення так само, як Angular порівнює input: за посиланням. Тому попередній урок актуальний і для сигнального стилю. Якщо треба інша логіка порівняння — її можна задати явно:
const user = signal(initial, { equal: (a, b) => a.id === b.id });
Куди все рухається
Zoneless-режим із модуля 3, уроку 1, працює саме на сигналах: без zone.js Angular не має іншого способу дізнатись про зміну, крім явного повідомлення. Тобто сигнали — це не просто зручний синтаксис, а фундамент, на якому будується наступне покоління change detection.
- Стан компонента тримай у сигналах, не в звичайних полях.
- Похідні значення —
computed, а не методи в шаблоні. OnPushусе одно став: він відсікає гілки цілком.- Оновлюй незмінно, навіть із сигналами.
- Не змішувати: половина стану в сигналах, половина в полях.
- Не читати сигнал у
effect, щоб «оновити» інший сигнал. - Не залишати ручні підписки там, де достатньо
toSignal(модуль 4). - Не вважати, що сигнал звільняє від
trackу@for.