Frontend Development 16 min read

Understanding Vue 3.0 Reactive Data: New Mechanisms and Their Impact

This article explains how Vue 3.0 rewrites its reactivity system using Proxy and Reflet, introduces the reactive, effect, and computed APIs, compares them with MobX, and details the resulting changes for arrays, collections, lazy observation, and IE compatibility.

政采云技术
政采云技术
政采云技术
Understanding Vue 3.0 Reactive Data: New Mechanisms and Their Impact

Vue 3.0 entered pre‑alpha during the National Day holiday, promising a faster, smaller, and more maintainable framework. To achieve this, the core was rewritten with TypeScript, a function‑based API, a new compiler, a revamped virtual DOM, and a completely new reactive mechanism.

The new reactivity API (reactive, effect, computed) feels similar to the MobX library used in React. The following example shows a minimal Vue 3 app that creates a reactive state, defines a computed value, and registers an effect to log changes:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <script src="../packages/vue/dist/vue.global.js"></script>
</head>
<body>
  <div id="app"></div>
  <script>
    const { reactive, computed, effect, createApp } = Vue
    const App = {
      template: `
        <div id="box">
            <button @click="add">{{ state.count }}</button>
        </div>
      `,
      setup() {
        const state = reactive({ count: 0 })
        function add() { state.count++ }
        effect(() => { console.log('count changed', state.count) })
        return { state, add }
      }
    }
    createApp(App).mount('#app')
  </script>
</body>
</html>

For comparison, a MobX snippet demonstrates similar concepts:

import { observable, computed, autorun } from "mobx"
var numbers = observable([1, 2, 3])
var sum = computed(() => numbers.reduce((a, b) => a + b, 0))
var disposer = autorun(() => console.log(sum.get())) // logs 6
numbers.push(4) // logs 10
numbers.push(5)

Vue 3 exposes three key reactive helpers:

reactive(value) – creates an observable object from primitives, objects, arrays, Maps, Sets, etc.

effect(fn) – runs a side‑effect immediately and re‑runs it whenever any observed property used inside changes.

computed(() => expression) – returns a cached value that recomputes only when its dependent observables change.

One major improvement over Vue 2.x is full array interception. Vue 2 only tracked seven mutating methods (push, pop, shift, unshift, splice, sort, reverse). Vue 3 uses Proxy to trap every get and set operation, enabling complete observation of index changes. The following Vue 2‑style Object.defineProperty example illustrates the old limitation:

const arr = ["2019","云","栖","音","乐","节"]
arr.forEach((val, index) => {
  Object.defineProperty(arr, index, {
    set(newVal) { console.log('assign') },
    get() { console.log('read'); return val }
  })
})
let index = arr[1] // read
arr[0] = "2050"   // assign

With Proxy , the same behavior becomes simpler:

const arr = ["2019","云","栖","音","乐","节"]
let ProxyArray = new Proxy(arr, {
  get(target, name) { console.log('read'); return Reflect.get(target, name) },
  set(target, name, value) { console.log('assign'); return Reflect.set(target, name, value) }
})
const index = ProxyArray[0] // read
ProxyArray[0] = "2050"   // assign

Vue 3 also introduces "lazy observation" (惰性监听). Developers can now decide which objects become reactive, improving component initialization speed and reducing memory usage because unused data no longer incurs deep Object.defineProperty traversal.

Collections such as Map and Set are now observable because Proxy can intercept them. A naïve proxy of a Map throws an error, so Vue wraps collection methods to bind the original this correctly:

let map = new Map([["name","zhengcaiyun"]])
let mapProxy = new Proxy(map, {
  get(target, key, receiver) {
    const value = Reflect.get(...arguments)
    return typeof value === 'function' ? value.bind(target) : value
  }
})
mapProxy.get("name") // works

The core implementation creates a reactive object by selecting either mutableHandlers for normal objects or mutableCollectionHandlers for collections:

function reactive(target) {
  return createReactiveObject(target, rawToReactive, reactiveToRaw, mutableHandlers, mutableCollectionHandlers)
}
function createReactiveObject(target, toProxy, toRaw, baseHandlers, collectionHandlers) {
  const handlers = collectionTypes.has(target.constructor) ? collectionHandlers : baseHandlers
  const observed = new Proxy(target, handlers)
  toProxy.set(target, observed)
  toRaw.set(observed, target)
  if (!targetMap.has(target)) targetMap.set(target, new Map())
  return observed
}

Collection handlers expose only a get trap that redirects method calls to instrumented versions, enabling reactive size , add , delete , and iteration methods.

export const mutableCollectionHandlers = { get: createInstrumentationGetter(mutableInstrumentations) }
export const mutableInstrumentations = {
  get(key) { return get(this, key, toReactive) },
  get size() { return size(this) },
  has, add, set, delete: deleteEntry, clear,
  forEach: createForEach(false)
}
const iteratorMethods = ['keys','values','entries', Symbol.iterator]
iteratorMethods.forEach(method => {
  mutableInstrumentations[method] = createIterableMethod(method, false)
})
function createInstrumentationGetter(instrumentations) {
  return function getInstrumented(target, key, receiver) {
    target = hasOwn(instrumentations, key) && key in target ? instrumentations : target
    return Reflect.get(target, key, receiver)
  }
}

Because Vue 3 relies on Proxy and Reflect , it cannot run on browsers that lack these features, such as Internet Explorer 11 and below. The team plans to support IE 11 until the final release, but older versions are effectively unsupported.

In summary, Vue 3’s reactivity overhaul brings full array and collection tracking, lazy observation, and a more ergonomic API, while sacrificing legacy IE compatibility in favor of modern JavaScript capabilities.

frontendJavaScriptProxyVueReactiveMobX
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

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.