Frontend Development 14 min read

How React, Angular, and Vue Detect Changes and Perform Batch Updates

This article examines how modern frontend frameworks—React, Angular 1, Angular 2, and Vue—detect data changes and implement batch updates, comparing their virtual DOM diffing, dirty checking, zone.js, and asynchronous queues to reveal each library’s underlying change‑detection strategy.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
How React, Angular, and Vue Detect Changes and Perform Batch Updates

Introduction

In traditional web development, developers manually fetch data and update the DOM, which is error‑prone and hard to maintain for complex pages. Modern frameworks such as React, Angular, and Vue let developers focus on data, automatically updating the DOM when data changes. This article analyses how these frameworks detect data changes and perform batch updates.

React

Virtual DOM

React creates two virtual DOM trees from the old and new state, compares them with a diff algorithm, and updates only the changed parts of the real DOM. Data changes are signaled by calling

setState

.

setState

Example component (image):

When the button calls

this.setState({val: 1})

, React updates

this.state.val

to 1 and re‑renders the UI. If

setState

is called multiple times in the same event handler, React batches the updates instead of applying them synchronously.

Testing with three scenarios—events, timers, and XHR—shows that calls made inside React’s own event handlers are batched, while those triggered from asynchronous callbacks are applied immediately.

In React‑invoked methods, consecutive setState calls are batched; otherwise they are applied immediately.

Thus, React’s batch update relies on the execution context of the call.

Transaction

React uses a transaction system to wrap functions, invoking

initialize

before execution and

close

after, enabling batch updates.

The core

setState

implementation checks

batchingStrategy.isBatchingUpdates

to decide between

batchedUpdates

and

dirtyComponents.push

, as illustrated in the diagram.

Summary: React detects changes via

setState

, uses transactions for batching, and updates the DOM through virtual DOM diffing.

Angular 1

Dirty Checking

Angular 1 traverses all scopes from

$rootScope

, comparing each watcher’s previous and current values to decide whether to update the DOM.

Watchers contain

eq

,

exp

,

fn

,

get

, and

last

fields.

$apply

Angular 1 triggers dirty checking by calling

$scope.$apply()

. The framework automatically invokes

$apply

for built‑in events, timers, and $http, but developers must call it manually when using external libraries.

When code runs outside Angular’s context (e.g., jQuery event handlers),

$apply

must be invoked manually to trigger change detection.

Summary: Angular 1 relies on manual or framework‑wrapped

$apply

to perform dirty checking and batch updates.

Angular 2

Angular 2 traverses the component tree from the root, comparing old and new data to decide updates. It uses a unidirectional data flow and offers change‑detection strategies such as

OnPush

, which checks object references instead of deep traversal.

It can perform hundreds of thousands of checks within a couple of milliseconds. — Pascal Precht

Images illustrate the default and OnPush strategies.

Zone.js

Angular 2 uses Zone.js to capture the execution context of asynchronous operations (setTimeout, XHR, event listeners). Zone.js patches these APIs and provides hooks that trigger change detection after each task.

When the main function and a timeout finish, Zone.js notifies Angular to run a digest cycle, enabling batch updates without manual calls.

Summary: Zone.js allows Angular 2 to perform automatic batch updates in any asynchronous context.

Vue

Vue creates a watcher for each data binding using

Object.defineProperty

to define getters and setters, allowing it to detect changes.

setter

When data changes, Vue batches updates by queuing them within the same event loop, flushing the queue on the next tick. This behavior is consistent across events, timers, and XHR.

Asynchronous Update Queue

Whenever a data change is observed, Vue pushes it into a queue; duplicate watchers are de‑duplicated. The queue is flushed on the next event loop tick, using MutationObserver or setTimeout(fn, 0) as a fallback.

Vue’s implementation leverages JavaScript’s single‑threaded nature and the event queue to achieve batch updates.

config.async

Setting

Vue.config.async = false

disables the asynchronous queue, causing synchronous DOM updates, which is useful for debugging but not recommended for production.

If async mode is disabled, Vue updates the DOM synchronously, which may degrade performance and affect watcher callback order.

Summary: Vue detects changes via getters/setters, batches updates using an async queue, and can be forced into synchronous mode for debugging.

Conclusion

This analysis compares the change‑detection and batch‑update mechanisms of React, Angular 1/2, and Vue. React and Angular 1 use execution context to batch updates, Angular 2 relies on Zone.js, and Vue employs ES5 getters/setters with the JavaScript event loop to achieve efficient batch updates.

ReactVueAngularBatch UpdateFrontend FrameworksChange Detection
Tencent IMWeb Frontend Team
Written by

Tencent IMWeb Frontend Team

IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.