tezvyn:

How do Vue and Angular detect nested object mutations?

AI-drafted, machine-checkedSource: vuejs.orgadvanced

Tests deep reactivity vs reference-based detection. Vue 3 Proxies catch nested mutations; Angular Default checks on zone ticks and OnPush misses same-reference changes. Fix via immutability, deep watchers, or ngDoCheck.

WHAT THIS TESTS: This question probes whether you understand the fundamental difference between Vue's fine-grained reactive system and Angular's top-down change detection tree. It reveals if you know how Proxy-based observation works versus zone.js dirty checking, and whether you can architect around the limitations of each framework without resorting to anti-patterns.

A GOOD ANSWER COVERS: First, explain that Vue 3 uses ES Proxies to recursively wrap objects assigned to reactive() or ref(), which means reading or mutating a nested property is automatically tracked and triggers updates in dependent templates, computed properties, and watchers. Second, contrast this with Angular, whose Default strategy relies on zone.js to trigger digest cycles after async events; during these cycles Angular re-evaluates template expressions but does not deep-watch input objects, so while a Default component may display updated nested values after a zone event, the ngOnChanges hook will not fire and OnPush components will skip re-rendering entirely because the input reference is unchanged. Third, identify the bugs that arise from this mismatch, such as stale UI in OnPush branches, missed ngOnChanges side effects, and silent state corruption when child components mutate parent-owned objects. Fourth, list concrete fixes in order of preference: enforce immutability so new references propagate through inputs and reactive dependencies; use Vue deep watchers or watchEffect when you must react to nested changes in a specific object; and in Angular implement ngDoCheck with KeyValueDiffers or IterableDiffers to perform manual deep diffs when you are forced to work with mutable references, optionally calling ChangeDetectorRef.markForCheck() if using OnPush.

COMMON WRONG ANSWERS: A major red flag is stating that Angular Default performs automatic deep observation on input objects. Another is suggesting that two-way binding or direct prop mutation is a valid fix, since this breaks unidirectional data flow and creates unpredictable side effects. Candidates also err by claiming Vue requires deep true on every nested watch, which confuses ref unwrapping behavior with explicit deep observation of plain objects in watchers.

LIKELY FOLLOW-UPS: The interviewer may ask how OnPush changes the equation in Angular, when you would choose shallowRef or shallowReactive in Vue to opt out of deep conversion, or how signals in modern Angular or Vue affect this scenario. They might also ask you to compare the performance cost of Angular manual diffing in ngDoCheck versus simply enforcing immutable updates.

ONE CONCRETE EXAMPLE: Imagine a parent passes a config object to a child. In Vue, if the parent holds this object in a ref and the child reads config.theme.color, the dependency is tracked; mutating config.theme.color elsewhere updates the child automatically. In Angular Default, the child template shows config.theme.color but ngOnChanges is silent when the nested property changes; if the child uses OnPush, the view never updates until the parent passes a new config reference. The robust fix is for the parent to replace the object with a spread like config equals a new object spreading config and theme set to a new object spreading config.theme with color set to blue, giving Angular a new reference and Vue a new reactive graph edge without needing deep watchers.

Read the original → vuejs.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.