Vue 3 Reactivity: Proxies vs. Vue 2 Reactivity

Hero image for Vue 3 Reactivity: Proxies vs. Vue 2 Reactivity. Image by Bruce Warrington.
Hero image for 'Vue 3 Reactivity: Proxies vs. Vue 2 Reactivity.' Image by Bruce Warrington.

One of the biggest improvements in Vue 3 is its completely redesigned reactivity system. While effective, Vue 2's reactivity system had some notable limitations, especially when working with arrays or dynamically adding properties. Vue 3 leverages JavaScript's builtin Proxy feature to solve many of these issues.

In this article, I intend to explore the differences between Vue 2's reactivity approach and Vue 3's use of Proxies and explain how each system works and why Vue made the switch.


How Reactivity Worked in Vue 2

Before looking at Vue 3's improvements, it makes sense for us to briefly revisit how Vue 2's reactivity works.

Vue 2: Object.defineProperty()

In Vue 2, the reactivity system relied heavily on JavaScript's Object.defineProperty() method (which I've written about in the past here). This method defines getters and setters on object properties, allowing Vue to detect and respond to changes, like this:

const data = {};Object.defineProperty(data, 'message', {  get() {    console.log('Accessing message');    return 'Hello';  },  set(newValue) {    console.log('Updating message to:', newValue);  },});

Whenever the message property is changed or accessed, Vue's reactive system notices and updates the DOM accordingly.

Limitations of Vue 2 Reactivity

This approach has a few limitations:

  • New properties added after initialisation are not reactive.
  • Array modifications require special methods (push, splice, etc.) to trigger updates.
  • It cannot detect changes to properties that weren't initially defined.

These limitations would often lead to developers using hacks and workarounds, which in turn makes those applications harder to maintain and less intuitive.


How Vue 3 Uses Proxies for Reactivity

Vue 3 addresses these shortcomings by using JavaScript Proxies, which are much more powerful, flexible, and bettersuited than getters and setters.

What are JavaScript Proxies?

A Proxy is an object which wraps another object (the 'target') and then intercepts operations such as reading, writing, or deleting properties. It can then handle these operations or pass them through to the underlying object.

Here's a quick example:

const target = { message: 'Hello' };const proxy = new Proxy(target, {  get(target, prop) {    console.log(`Property "${String(prop)}" read.`);    return target[prop];  },  set(target, prop, value) {    console.log(`Property "${String(prop)}" updated to "${value}"`);    target[prop] = value;    return true;  },});console.log(proxy.message);  // logs "Hello"proxy.message = 'Hi!';  // triggers setter

In Vue 3, this means that the underlying framework can track changes and modifications far more efficiently than before.


How Vue 3 Uses Proxies for Enhanced Reactivity

By adopting Proxies, Vue 3's reactivity system provides several advantages:

Dynamic Property Reactivity

Properties added after initialisation become reactive automatically, for example:

const state = Vue.reactive({});// Adding a new reactive property dynamicallystate.newMessage = 'Hello Vue!';

This means that Vue 3 immediately tracks and responds to a new property, something that Vue 2 could not easily do.

Better Array Reactivity

Arrays in Vue 3 become fully reactive by default. All standard array operations are tracked automatically without needing those hacky special methods:

const state = reactive({ items: ['a', 'b', 'c'] });state.items.push('d');  // Vue 3 detects this automatically

As you can probably see, this is a far simpler and cleaner approach compared to Vue 2's use of special array methods like Vue.set() or array mutation.


Comparing Vue 2 and Vue 3 Reactivity

To summarise, here's a brief overview of the main differences between the two approaches:

FeatureVue 2 ReactivityVue 3 Reactivity
ImplementationGetters/SettersJavaScript Proxies
New PropertiesRequire manual initialisationAutomatically reactive
Array ReactivityLimited, special methods neededFully reactive without workarounds
PerformanceModerate performance overheadBetter performance due to native Proxy
Browser SupportWider browser compatibilityRequires modern browsers

Browser Support and Polyfills

You will probably have spotted in that table above, the potential pitfall with this approach is browser support. Because Vue 3's reactivity system relies on JavaScript proxies, it limits browser support to more modern browsers only. These are:

  • Chrome 49+
  • Firefox 18+
  • Edge 12+
  • Safari 10+

Realistically, these are browsers that are already at least ten years old, but if your application does still need to support older browsers, then you'll need to include polyfills or otherwise consider sticking with Vue 2's reactivity for maximum compatibility.


Wrapping up

Vue 3's shift to JavaScript proxies represents a major improvement in how reactive data is managed. Proxies have removed many of the limitations faced by Vue 2's getterandsetter approach, which has simplified the creation of reactive applications. This change not only improves our experience with the framework as developers but also enhances performance and flexibility when building dynamic, interactive UIs.

Key Takeaways

  • Vue 2 used getters and setters (Object.defineProperty) to track changes, leading to certain limitations.
  • Vue 3 uses JavaScript proxies, offering improved flexibility and automatic reactivity.
  • Newly added properties and array operations become automatically reactive in Vue 3.
  • Proxies simplify reactivity, improve performance, and make state management more intuitive.
  • Browser support for proxies is strong, but older browsers require polyfills or fallbacks.

Understanding this shift to proxies gives us greater control and efficiency when building Vue applications, resulting in smoother development and more responsive interfaces.


Categories:

  1. Development
  2. Front‑End Development
  3. JavaScript
  4. Node.js
  5. Vue.js