Change Detection в Angular v17
Angular v16 представив Signal — абсолютно новий API, призначений запровадити детальну реактивність у додатках Angular. У версії v17 сигнали підвищують до стабільних (за винятком effect()), тож давайте подивимось, які можливості це дає для Change Detection.
Існуючий механізм виявлення змін
З моменту свого створення Angular покладається на zone.js і NgZone для планування виявлення змін шляхом виклику ApplicationRef.tick().
Починаючи з кореневого компонента, процес виявлення змін перевіряє компоненти у дереві компонентів, позначені як «брудні», і ті, які використовують стандартну стратегію виявлення змін. Цей комплексний підхід гарантує, що зміни виявляються та поширюються через всю ієрархію компонентів за потреби, зберігаючи цілісність потоку даних програми та інтерфейсу користувача.
Якщо Ви бажаєте більше дізнатися про існуючий механізм виявлення змін, до Вашої уваги стаття Angular 2+: Стратегия обнаружения изменений.
v17 презентує Local Change Detection
Сигнали були введені, щоб зробити можливим Local Change detection. У версії v16 живий сигнал (сигнал, викликаний у шаблоні), який оновлюється через Signal.set()
, Signal.mutate()
або computed()
, позначав компонент як брудний. Якщо більш детально, то компоненти позначаються як dirty через виклик внутрішньої функції markViewDirty()
, це та сама функція, яку викликає changeDetectionRef.markForCheck()
. У v17 цей виклик функції було замінено на markAncestorsForTraversal()
.
Ключова відмінність між цими двома функціями полягає в тому, що markViewDirty поширює своє «брудне» маркування на всі компоненти-предки рекурсивним способом, тоді як markAncestorsForTraversal обмежує «брудне» маркування поточним компонентом і планує його предків для майбутнього обходу без виклику негайної change detection. Тож зараз, покладаючись на виявлення змін на основі дерева, ми маємо доступ до global і local виявлення змін:
- Change Detection починається з кореневого компонента (global)
- Компонент з Default стратегією буде перевірено за замовчуванням
- Компонент OnPush буде перевірятися лише якщо він dirty
- Тепер ми маємо змогу позначити один компонент як dirty (local mode)
Починаючи з версії v17.0, local change detection доступне тільки при використаннні Signals, а markAncestorsForTraversal — приватне API.
Джерела: riegler.fr, angular.io