SoFunction
Updated on 2025-04-12

Vue 3 effect effect and principle analysis

Vue 3'sEffect (side effects)It is the core mechanism of the entire responsive system, responsible for managing dependency tracking and responsive triggering. Understanding its role and principles is crucial to mastering the underlying mechanisms of Vue.

1. Core role

1. Dependency Tracking

  • Automatically track the use of responsive data in side effect functions.

Sample code

import { reactive, effect } from 'vue'
const obj = reactive({ count: 0 })
effect(() => {
  (`count is: ${}`)
})
  • When executed for the first timeeffectWhen, function() => (...)Will be run.
  • TriggerofgetOperation, trigger dependency collection (replace the currenteffectRelated to)。

2. Automatic Re-run

When the dependency of responsive data changes, the side effect function is automatically re-executed:

++  // Trigger dependency update,Console Print "count is: 1"

3. Support advanced APIs

  • computedwatchThe underlying layers of component rendering functions, etc. all depend oneffectaccomplish.

II. Implementation principle

1. Core category: ReactiveEffect

Vue 3ReactiveEffectThe logic of class encapsulation side effects, the simplified source code structure is as follows:

class ReactiveEffect<T = any> {
  // All dependencies of the current effect (other responsive objects)  deps: Dep[] = []
  // Constructor parameters  constructor(
    public fn: () => T,            // Side effect function    public scheduler?: () => void  // Scheduling function (control the re-execution method)  ) {}
  // Run side effects (trigger dependency collection)  run() {
    activeEffect = this // Mark the currently running effect    try {
      return ()
    } finally {
      activeEffect = undefined
    }
  }
  // Stop listening  stop() { /* Remove itself from all dependencies */ }
}

2. Dependence collection process (Track)

Data structure

type Dep = Set<ReactiveEffect>    // Dependency collectiontype TargetMap = WeakMap<Object, Map<string, Dep>> // Globally dependent storage
  • Trigger timing: Responsive datagetWhen the operation is triggered.
  • process

    According to the responsive object (target) and key (key) Find deposittargetMapDependency set (dep)。

    Will currently activeactiveEffectAdd todepmiddle.

    At the same time,depjoin in(Reverse record, used for cleanup).

3. Trigger update (Trigger)

  • Trigger timing: Responsive datasetWhen operating.
  • process

    according totargetandkeyfromtargetMapGet the correspondingdepgather.

    TraversaldepAll ineffect

    • If there isscheduler(likecomputed), execute scheduler (optimize performance).
    • Otherwise, execute directly()

4. Scheduler

Allow controleffectHow to re-execute:

effect(() => {
  ()
}, {
  scheduler(effect) { 
    // If the effect is pushed into the microtask queue, it will be executed asynchronously    queueMicrotask() 
  }
})
  • Application scenarios:
    • watchAsynchronous batch update.
    • computedLazy update of the value of  .

3. Key optimization design

1. Nested Effect stack

Use stack structureeffectStackTrack nested effects:

function run() {
  if (!(this)) {
    try {
      ((activeEffect = this))
      return ()
    } finally {
      ()
      activeEffect = effectStack[ - 1]
    }
  }
}
  • Solve the problem: The dependency confusion when component nesting.

2. Cleanup mechanism

Clean up old dependencies before each effect execution:

function run() {
  cleanup(this) // Clean up old dependencies collected before  // ...and regain new dependencies}
  • Solve the problem: Invalid dependencies caused by dynamic branch logic (such asv-ifConditional dependency caused by switching).

3. Lazy execution

Configurable not to execute effect immediately:

const runner = effect(fn, { lazy: true })
runner() // Manual execution
  • Application scenarioscomputedDelay calculation when attribute initialization.

4. Relationship with Vue components

1. Component Rendering

ComponentsrenderThe function is wrapped ineffectmiddle:

function setupRenderEffect(instance) {
  effect(() => {
    const subTree = ()
    patch(, subTree)
     = subTree
  }, { scheduler: queueJob }) // Asynchronously update the queue}

2. Computed implementation

computedpasseffect+ Scheduler implements lazy update:

const computedRef = new ComputedRefImpl(
  getter,
  () => { // Scheduler    if (!this._dirty) {
      this._dirty = true
      trigger(this, 'set', 'value')
    }
  }
)

3. Watch API

watchbased oneffectThe scheduler implements asynchronous callbacks:

function watch(source, cb, { flush } = {}) {
  let scheduler
  if (flush === 'sync') {
    scheduler = cb
  } else { // 'post' or other default    scheduler = () => queuePostFlushCb(cb)
  }
  effect(() => traverse(source), { scheduler })
}

5. Comparison with Vue 2

characteristic Vue 2 (Watcher) Vue 3 (Effect)
Dependency tracking Triggered by traversing datagetter Automatic tracking with Proxy/Reflect
Update granularity Relying on component-level checking Targeted update based on precise dependency
Performance optimization Need to be handwrittenpureComputedwait Built-in automatic dependency cleaning and scheduling mechanism
Memory management Prone to memory leaks (old Dep reference issues) Automatically release useless dependencies through WeakMap

6. Source code flow diagram explanation

+---------------------+
|   Reactive Object   |
+----------+----------+
           │ When accessing properties
           ▼
+---------------------+
|   trigger get acting     +----→ track(target, key)
+---------------------+         │
           ▲                    ▼ Storage dependencies
           │          +---------------------+
           +----------+    targetMap        |
                      | (WeakMapstructure)        |
                      +---------+-----------+
                                │
                                ▼
                      +---------------------+
                      |   depsMap (Map)     |
                      | (key → Dep Set)      |
                      +---------+-----------+
                                │
                                ▼
                      +---------------------+
                      |   dep (Set)         |
                      | (Store all associated effect)|
                      +---------------------+

Summarize

Vue 3'seffectBecome the core of a responsive system through the following mechanisms:

  • Proxy dependency collection: Accurately track the use of responsive data.
  • Scheduler control: Provides flexible callback execution methods.
  • Memory security:passWeakMapAutomatically manage dependencies.
  • Framework-level optimization: Supports core functions such as component rendering, computing properties, and watch.

This is the end of this article about the role and principles of vue 3 effect. For more related content of vue 3 effect, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!