Vue 3 响应式系统源码解析

Vue 3 的响应式系统是其核心功能之一,它基于 JavaScript 的 Proxy API 实现。本文将按照推荐的阅读顺序,逐行解析响应式系统的关键源码。

🧠 响应式系统核心概念

在开始逐行解析之前,我们先了解一下 Vue 3 响应式系统的核心概念:

  1. 响应式数据: 能够自动追踪变化并触发更新的数据
  2. 副作用函数 (Effect): 访问响应式数据并可能产生副作用的函数
  3. 依赖收集: 当副作用函数访问响应式数据时,建立依赖关系
  4. 触发更新: 当响应式数据变化时,重新执行相关的副作用函数

📁 源码解析顺序

我们将按照以下顺序解析源码:

  1. ref.ts - Ref 的实现
  2. effect.tsdep.ts - 响应式系统的核心机制
  3. reactive.ts - reactive 的实现
  4. computed.ts - computed 的实现
  5. watch.ts - watch 的实现

1️⃣ Ref 实现解析 (ref.ts)

我们从最简单的响应式 API 开始,即 ref

typescript 复制代码
// ref.ts 文件开头引入相关依赖
import {
  type IfAny,
  hasChanged,
  isArray,
  isFunction,
  isObject,
} from '@vue/shared'

首先引入了来自 @vue/shared 的工具函数,这些函数用于类型检查和值比较。

typescript 复制代码
import { Dep, getDepFromReactive } from './dep'

引入了 Dep 类,它是依赖管理的核心类,用于收集和通知依赖。

typescript 复制代码
import {
  type Builtin,
  type ShallowReactiveMarker,
  isProxy,
  isReactive,
  isReadonly,
  isShallow,
  toRaw,
  toReactive,
} from './reactive'

reactive.ts 引入了响应式相关的工具函数和类型。

typescript 复制代码
import type { ComputedRef, WritableComputedRef } from './computed'
import { ReactiveFlags, TrackOpTypes, TriggerOpTypes } from './constants'
import { warn } from './warning'

引入了计算属性相关类型和常量定义。

typescript 复制代码
declare const RefSymbol: unique symbol
export declare const RawSymbol: unique symbol

export interface Ref<T = any, S = T> {
  get value(): T
  set value(_: S)
  /**
   * Type differentiator only.
   * We need this to be in public dts but don't want it to show up in IDE
   * autocomplete, so we use a private Symbol instead.
   */
  [RefSymbol]: true
}

定义了 Ref 接口,它包含一个 value 属性的 getter 和 setter。[RefSymbol] 是一个类型区分符,用于在类型系统中识别 Ref 对象。

typescript 复制代码
/**
 * Checks if a value is a ref object.
 *
 * @param r - The value to inspect.
 * @see {@link https://vuejs.org/api/reactivity-utilities.html#isref}
 */
export function isRef<T>(r: Ref<T> | unknown): r is Ref<T>
export function isRef(r: any): r is Ref {
  return r ? r[ReactiveFlags.IS_REF] === true : false
}

isRef 函数用于检查一个值是否为 Ref 对象,通过检查 [ReactiveFlags.IS_REF] 属性来判断。

typescript 复制代码
/**
 * Takes an inner value and returns a reactive and mutable ref object, which
 * has a single property `.value` that points to the inner value.
 *
 * @param value - The object to wrap in the ref.
 * @see {@link https://vuejs.org/api/reactivity-core.html#ref}
 */
export function ref<T>(
  value: T,
): [T] extends [Ref] ? IfAny<T, Ref<T>, T> : Ref<UnwrapRef<T>, UnwrapRef<T> | T>
export function ref<T = any>(): Ref<T | undefined>
export function ref(value?: unknown) {
  return createRef(value, false)
}

ref 函数创建一个响应式的 ref 对象。它有两种重载形式:

  1. 接收一个值并返回对应的 Ref 对象
  2. 不接收参数,返回一个 undefined 类型的 Ref 对象

实际实现委托给了 createRef 函数。

typescript 复制代码
declare const ShallowRefMarker: unique symbol

export type ShallowRef<T = any, S = T> = Ref<T, S> & {
  [ShallowRefMarker]?: true
}

定义了 ShallowRef 类型,它是一个浅层的 Ref,只追踪 .value 的变化,不追踪值内部的变化。

typescript 复制代码
/**
 * Shallow version of {@link ref}.
 *
 * @example
 * ```js
 * const state = shallowRef({ count: 1 })
 *
 * // does NOT trigger change
 * state.value.count = 2
 *
 * // does trigger change
 * state.value = { count: 2 }
 * ```
 *
 * @param value - The "inner value" for the shallow ref.
 * @see {@link https://vuejs.org/api/reactivity-advanced.html#shallowref}
 */
export function shallowRef<T>(
  value: T,
): Ref extends T
  ? T extends Ref
    ? IfAny<T, ShallowRef<T>, T>
    : ShallowRef<T>
  : ShallowRef<T>
export function shallowRef<T = any>(): ShallowRef<T | undefined>
export function shallowRef(value?: unknown) {
  return createRef(value, true)
}

shallowRef 创建一个浅层的响应式引用,只追踪 .value 的变化,而不追踪值内部的变化。

typescript 复制代码
function createRef(rawValue: unknown, shallow: boolean) {
  if (isRef(rawValue)) {
    return rawValue
  }
  return new RefImpl(rawValue, shallow)
}

createRef 是创建 Ref 的内部函数,如果传入的值已经是 Ref,则直接返回;否则创建一个新的 RefImpl 实例。

typescript 复制代码
class RefImpl<T> {
  private _value: T
  private _rawValue: T

  public dep?: Dep = undefined
  public readonly __v_isRef = true

  constructor(
    value: T,
    public readonly __v_isShallow: boolean,
  ) {
    this._rawValue = __v_isShallow ? value : toRaw(value)
    this._value = __v_isShallow ? value : toReactive(value)
  }

  get value() {
    trackRefValue(this)
    return this._value
  }

  set value(newVal) {
    const useDirectValue =
      this.__v_isShallow || isShallow(newVal) || isReadonly(newVal)
    newVal = useDirectValue ? newVal : toRaw(newVal)
    if (hasChanged(newVal, this._rawValue)) {
      this._rawValue = newVal
      this._value = useDirectValue ? newVal : toReactive(newVal)
      triggerRefValue(this, newVal)
    }
  }
}

RefImpl 是 Ref 的具体实现类:

  1. _value: 存储当前值
  2. _rawValue: 存储原始值(未被 Proxy 包装)
  3. dep: 依赖管理对象
  4. __v_isRef: 标识这是一个 Ref 对象
  5. __v_isShallow: 标识是否为浅层响应式

构造函数中,根据是否为浅层响应式来决定如何处理传入的值。

getter 中调用 trackRefValue 进行依赖收集。

setter 中:

  • 首先判断是否应该直接使用新值
  • 将新值转换为原始值
  • 比较新旧值,如果发生变化则更新值并调用 triggerRefValue 触发更新
typescript 复制代码
export function triggerRefValue(ref: RefBase<any>, newVal?: any) {
  ref = toRaw(ref)
  const dep = ref.dep
  if (dep) {
    if (__DEV__) {
      dep.notify({
        type: TriggerOpTypes.SET,
        target: ref,
        key: 'value',
        newValue: newVal,
      })
    } else {
      dep.notify()
    }
  }
}

triggerRefValue 函数用于触发 Ref 的更新,通知所有依赖这个 Ref 的副作用函数重新执行。

typescript 复制代码
export function trackRefValue(ref: RefBase<any>) {
  if (shouldTrack && activeEffect) {
    ref = toRaw(ref)
    if (__DEV__) {
      trackEffects(
        ref.dep || (ref.dep = createDep()),
        {
          target: ref,
          type: TrackOpTypes.GET,
          key: 'value',
        },
      )
    } else {
      trackEffects(ref.dep || (ref.dep = createDep()))
    }
  }
}

trackRefValue 函数用于收集对 Ref 的依赖,当 Ref 的值被访问时调用。

2️⃣ Effect 和 Dep 实现解析

Effect 实现 (effect.ts)

typescript 复制代码
export interface ReactiveEffectOptions extends DebuggerOptions {
  lazy?: boolean
  scheduler?: EffectScheduler
  allowRecurse?: boolean
  onStop?: () => void
}

定义了 ReactiveEffectOptions 接口,用于配置副作用函数的行为。

typescript 复制代码
export class ReactiveEffect<T = any> {
  active = true
  deps: Dep[] = []
  parent: ReactiveEffect | undefined = undefined

  /**
   * Can be attached after creation
   * @internal
   */
  computed?: ComputedRefImpl<T>
  /**
   * @internal
   */
  allowRecurse?: boolean
  /**
   * @internal
   */
  private deferStop?: boolean

  onStop?: () => void
  // dev only
  onTrack?: (event: DebuggerEvent) => void
  // dev only
  onTrigger?: (event: DebuggerEvent) => void

  /**
   * @internal
   */
  _dirtyLevel = DirtyLevels.Dirty
  /**
   * @internal
   */
  _trackId = 0
  /**
   * @internal
   */
  _runnings = 0
  /**
   * @internal
   */
  _shouldSchedule = false
  /**
   * @internal
   */
  _depsLength = 0

  constructor(
    public fn: () => T,
    public trigger: () => void,
    public scheduler?: EffectScheduler,
    scope?: EffectScope,
  ) {
    recordEffectScope(this, scope)
  }
}

ReactiveEffect 类是副作用函数的核心实现:

  1. active: 标识副作用函数是否处于活跃状态
  2. deps: 存储该副作用函数依赖的所有 Dep 对象
  3. parent: 指向父级副作用函数(处理嵌套情况)
  4. fn: 实际的副作用函数
  5. scheduler: 调度器,控制副作用函数的执行时机
  6. 其他内部属性用于优化和调试
typescript 复制代码
export function effect<T = any>(
  fn: () => T,
  options?: ReactiveEffectOptions,
): ReactiveEffectRunner {
  if ((fn as ReactiveEffectRunner)._isEffect) {
    fn = (fn as ReactiveEffectRunner).effect.fn
  }

  const _effect = new ReactiveEffect(fn, NOOP, () => {
    if (_effect.dirty) {
      _effect.run()
    }
  })
  if (options) {
    extend(_effect, options)
    if (options.scope) recordEffectScope(_effect, options.scope)
  }
  if (!options || !options.lazy) {
    _effect.run()
  }
  const runner = _effect.run.bind(_effect) as ReactiveEffectRunner
  runner.effect = _effect
  return runner
}

effect 函数用于创建一个副作用函数:

  1. 如果传入的函数已经是副作用函数,则获取其原始函数
  2. 创建 ReactiveEffect 实例
  3. 应用配置选项
  4. 如果不是懒执行,则立即运行一次
  5. 返回一个绑定到 _effect.run 的运行器函数
typescript 复制代码
run() {
  if (!this.active) {
    return this.fn()
  }
  let parent: ReactiveEffect | undefined = activeEffect
  let lastShouldTrack = shouldTrack
  while (parent && lastShouldTrack) {
    if (parent === this) {
      return
    }
    parent = parent.parent
  }
  try {
    this.parent = activeEffect
    activeEffect = this
    shouldTrack = true

    trackOpBit = 1 << ++effectTrackDepth

    if (effectTrackDepth <= maxMarkerBits) {
      initDepMarkers(this)
    } else {
      cleanupEffect(this)
    }
    return this.fn()
  } finally {
    if (effectTrackDepth <= maxMarkerBits) {
      finalizeDepMarkers(this)
    }

    trackOpBit = 1 << --effectTrackDepth

    activeEffect = this.parent
    shouldTrack = lastShouldTrack
    this.parent = undefined

    if (this.deferStop) {
      this.stop()
    }
  }
}

run 方法是执行副作用函数的核心逻辑:

  1. 检查副作用函数是否处于活跃状态
  2. 设置父子关系,防止循环调用
  3. 设置全局状态(activeEffectshouldTrack
  4. 初始化依赖标记
  5. 执行副作用函数
  6. 清理和恢复状态

Dep 实现 (dep.ts)

typescript 复制代码
export class Dep {
  activeLink?: Link = undefined
  subs?: Link = undefined
  subsHead?: Link
  map?: KeyToDepMap = undefined
  key?: unknown = undefined
  sc: number = 0

  constructor(public computed?: ComputedRefImpl | undefined) {
    if (__DEV__) {
      this.subsHead = undefined
    }
  }
}

Dep 类用于管理依赖关系:

  1. activeLink: 指向当前活跃的依赖链接
  2. subs: 指向订阅者链表的尾部
  3. subsHead: 指向订阅者链表的头部(开发模式下使用)
  4. mapkey: 用于对象属性的依赖清理
  5. sc: 订阅者计数器
typescript 复制代码
track(debugInfo?: DebuggerEventExtraInfo): Link | undefined {
  if (!activeEffect || !shouldTrack || activeEffect === this.computed) {
    return
  }

  let link = this.activeLink
  if (link === undefined || link.sub !== activeEffect) {
    link = this.activeLink = new Link(activeEffect, this)

    if (!activeEffect.deps) {
      activeEffect.deps = activeEffect.depsTail = link
    } else {
      link.prevDep = activeEffect.depsTail
      activeEffect.depsTail!.nextDep = link
      activeEffect.depsTail = link
    }

    if (__DEV__ && debugInfo) {
      link.debugInfo = debugInfo
    }
  }

  return link
}

track 方法用于收集依赖:

  1. 检查是否应该收集依赖
  2. 如果当前副作用函数尚未订阅此 Dep,则创建新的链接
  3. 将链接添加到副作用函数的依赖链表中
  4. 返回链接对象
typescript 复制代码
trigger(debugInfo?: DebuggerEventExtraInfo): void {
  let link = this.subs
  while (link) {
    const { sub } = link
    if (sub.notify(debugInfo)) {
      const currentEffect = activeSub
      activeSub = sub
      try {
        sub.trigger()
      } finally {
        activeSub = currentEffect
      }
    }
    link = link.prevSub
  }
}

trigger 方法用于触发更新:

  1. 遍历所有订阅者
  2. 调用订阅者的 notify 方法
  3. 如果需要触发,则调用订阅者的 trigger 方法

3️⃣ Reactive 实现解析 (reactive.ts)

typescript 复制代码
export function reactive<T extends object>(target: T): Reactive<T>
export function reactive(target: object) {
  // if trying to observe a readonly proxy, return the readonly version.
  if (isReadonly(target)) {
    return target
  }
  return createReactiveObject(
    target,
    false,
    mutableHandlers,
    mutableCollectionHandlers,
    reactiveMap,
  )
}

reactive 函数用于创建响应式对象:

  1. 如果目标对象已经是只读的,则直接返回
  2. 调用 createReactiveObject 创建响应式对象
typescript 复制代码
function createReactiveObject(
  target: Target,
  isReadonly: boolean,
  baseHandlers: ProxyHandler<any>,
  collectionHandlers: ProxyHandler<any>,
  proxyMap: WeakMap<Target, any>,
) {
  if (!isObject(target)) {
    if (__DEV__) {
      warn(`value cannot be made reactive: ${String(target)}`)
    }
    return target
  }
  // target is already a Proxy, return it.
  // exception: calling readonly() on a reactive object
  if (
    target[ReactiveFlags.RAW] &&
    !(isReadonly && target[ReactiveFlags.IS_REACTIVE])
  ) {
    return target
  }
  // target already has corresponding Proxy
  const existingProxy = proxyMap.get(target)
  if (existingProxy) {
    return existingProxy
  }
  // only specific value types can be observed.
  const targetType = getTargetType(target)
  if (targetType === TargetType.INVALID) {
    return target
  }
  const proxy = new Proxy(
    target,
    targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers,
  )
  proxyMap.set(target, proxy)
  return proxy
}

createReactiveObject 是创建响应式对象的核心函数:

  1. 检查目标是否为对象,如果不是则直接返回
  2. 检查目标是否已经是 Proxy,如果是则直接返回
  3. 检查是否已存在对应的 Proxy,如果存在则返回已存在的
  4. 检查目标类型是否可以被观察
  5. 根据目标类型选择合适的处理器创建 Proxy
  6. 将 Proxy 存入映射表并返回

4️⃣ Computed 实现解析 (computed.ts)

typescript 复制代码
export function computed<T>(
  getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>,
  debugOptions?: DebuggerOptions,
  isSSR = false,
): ComputedRef<T> {
  let getter: ComputedGetter<T>
  let setter: ComputedSetter<T> | undefined

  const onlyGetter = isFunction(getterOrOptions)
  if (onlyGetter) {
    getter = getterOrOptions
    setter = __DEV__
      ? () => {
          warn('Write operation failed: computed value is readonly')
        }
      : NOOP
  } else {
    getter = getterOrOptions.get
    setter = getterOrOptions.set
  }

  const cRef = new ComputedRefImpl(getter, setter, isSSR)
  
  if (__DEV__ && debugOptions && !isSSR) {
    cRef.onTrack = debugOptions.onTrack
    cRef.onTrigger = debugOptions.onTrigger
  }

  return cRef as any
}

computed 函数用于创建计算属性:

  1. 解析 getter 和 setter
  2. 对于只读计算属性,设置一个警告的 setter
  3. 创建 ComputedRefImpl 实例
  4. 应用调试选项
  5. 返回计算属性引用
typescript 复制代码
export class ComputedRefImpl<T> {
  public dep?: Dep = undefined

  private _value!: T
  public readonly effect: ReactiveEffect<T>

  public readonly __v_isRef = true
  public readonly __v_isReadonly: boolean = false

  public _dirty = true
  public _cacheable: boolean

  constructor(
    getter: ComputedGetter<T>,
    public readonly _setter: ComputedSetter<T>,
    isSSR: boolean,
  ) {
    this.effect = new ReactiveEffect(getter, () => {
      if (!this._dirty) {
        this._dirty = true
        triggerRefValue(this)
      }
    })
    this.effect.computed = this
    this.effect.active = this._cacheable = !isSSR
    this.__v_isReadonly = isFunction(getter)
  }

  get value() {
    // the computed ref may get wrapped by other proxies e.g. readonly() #3376
    const self = toRaw(this)
    trackRefValue(self)
    if (self._dirty || !self._cacheable) {
      self._dirty = false
      self._value = self.effect.run()!
    }
    return self._value
  }

  set value(newValue: T) {
    this._setter(newValue)
  }
}

ComputedRefImpl 是计算属性的具体实现:

  1. dep: 依赖管理对象
  2. _value: 缓存的计算结果
  3. effect: 用于计算值的副作用函数
  4. _dirty: 标识计算结果是否需要重新计算
  5. _cacheable: 标识是否可以缓存结果

getter 中:

  1. 进行依赖收集
  2. 如果值是"脏"的或者不可缓存,则重新计算
  3. 返回缓存的值

setter 中直接调用 _setter 函数

5️⃣ Watch 实现解析 (watch.ts)

typescript 复制代码
export function watch<T = any, Immediate extends Readonly<boolean> = false>(
  source: T | WatchSource<T>,
  cb: any,
  options?: WatchOptions<Immediate>,
): WatchStopHandle {
  if (__DEV__ && !isFunction(cb)) {
    warn(
      `\`watch(fn, options?)\` signature has been moved to a separate API. ` +
        `Use \`watchEffect(fn, options?)\` instead. \`watch\` now only ` +
        `supports \`watch(source, cb, options?) signature.`,
    )
  }
  return doWatch(source as any, cb, options)
}

watch 函数用于创建侦听器:

  1. 检查回调函数是否为函数类型
  2. 委托给 doWatch 函数执行实际逻辑
typescript 复制代码
function doWatch(
  source: WatchSource | WatchSource[] | WatchEffect | object,
  cb: WatchCallback | null,
  { immediate, deep, flush, onTrack, onTrigger }: WatchOptions = EMPTY_OBJ,
): WatchStopHandle {
  if (__DEV__ && !cb) {
    // ...
  }

  const warnInvalidSource = (s: unknown) => {
    warn(
      `Invalid watch source: `,
      s,
      `A watch source can only be a getter/effect function, a ref, ` +
        `a reactive object, or an array of these types.`,
    )
  }

  const instance = currentInstance
  const call = (fn: Function, type: WatchErrorCodes, args?: unknown[]) =>
    invokeWithErrorHandling(fn, null, args, instance, type)

  let getter: () => any
  let forceTrigger = false
  let isMultiSource = false

  if (isRef(source)) {
    getter = () => source.value
    forceTrigger = isShallow(source)
  } else if (isReactive(source)) {
    getter = () => source
    deep = true
  } else if (isArray(source)) {
    isMultiSource = true
    forceTrigger = source.some(s => isReactive(s))
    getter = () =>
      source.map(s => {
        if (isRef(s)) {
          return s.value
        } else if (isReactive(s)) {
          return traverse(s)
        } else if (isFunction(s)) {
          return call(s, WatchErrorCodes.WATCH_GETTER)
        } else {
          __DEV__ && warnInvalidSource(s)
        }
      })
  } else if (isFunction(source)) {
    if (cb) {
      // getter with cb
      getter = () =>
        call(source, WatchErrorCodes.WATCH_GETTER)
    } else {
      // no cb -> simple effect
      getter = () => {
        if (instance && instance.isUnmounted) {
          return
        }
        if (cleanup) {
          cleanup()
        }
        return call(source, WatchErrorCodes.WATCH_CALLBACK, [onCleanup])
      }
    }
  } else {
    getter = NOOP
    __DEV__ && warnInvalidSource(source)
  }

  if (cb && deep) {
    const baseGetter = getter
    getter = () => traverse(baseGetter())
  }

  let cleanup: (() => void) | undefined
  let onCleanup: OnCleanup = (fn: () => void) => {
    cleanup = effect.onStop = () => {
      call(fn, WatchErrorCodes.WATCH_CLEANUP)
    }
  }

  let oldValue: any = isMultiSource
    ? new Array((source as []).length).fill(INITIAL_WATCHER_VALUE)
    : INITIAL_WATCHER_VALUE

  const job: SchedulerJob = () => {
    if (!effect.active) {
      return
    }
    if (cb) {
      // watch(source, cb)
      const newValue = effect.run()
      if (
        deep ||
        forceTrigger ||
        (isMultiSource
          ? (newValue as any[]).some((v, i) =>
              hasChanged(v, (oldValue as any[])[i]),
            )
          : hasChanged(newValue, oldValue))
      ) {
        // cleanup before running cb again
        if (cleanup) {
          cleanup()
        }
        call(cb, WatchErrorCodes.WATCH_CALLBACK, [
          newValue,
          // pass undefined as the old value when it's changed for the first time
          oldValue === INITIAL_WATCHER_VALUE
            ? undefined
            : isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE
              ? []
              : oldValue,
          onCleanup,
        ])
        oldValue = newValue
      }
    } else {
      // watchEffect
      effect.run()
    }
  }

  // important: mark the job as a watcher callback so that scheduler knows
  // it is allowed to self-trigger (#1727)
  job.allowRecurse = !!cb

  let scheduler: EffectScheduler
  if (flush === 'sync') {
    scheduler = job as any // the scheduler function gets called directly
  } else if (flush === 'post') {
    scheduler = () => queuePostRenderEffect(job, instance && instance.suspense)
  } else {
    // 'pre'
    job.pre = true
    if (instance) job.id = instance.uid
    scheduler = () => queueJob(job)
  }

  const effect = new ReactiveEffect(getter, NOOP, scheduler)

  const update = effect.run.bind(effect)
  update()

  const unwatch = () => {
    if (effect.active) {
      cleanupEffect(effect)
      if (cleanup) {
        cleanup()
      }
    }
  }

  return unwatch
}

doWatch 函数是 watch 的核心实现:

  1. 根据不同类型的数据源创建对应的 getter 函数
  2. 处理 deep 侦听的情况
  3. 创建清理函数机制
  4. 创建调度器,控制回调函数的执行时机
  5. 创建副作用函数并立即执行一次
  6. 返回停止侦听的函数

📊 总结

Vue 3 的响应式系统是一个复杂而精妙的设计,通过以下几个核心概念协同工作:

  1. Ref : 通过 getter/setter 拦截对 .value 的访问和修改
  2. Reactive: 通过 Proxy 拦截对对象属性的访问和修改
  3. Effect: 包装副作用函数,建立数据和副作用之间的联系
  4. Dep: 管理依赖关系,当数据变化时通知相关的副作用函数
  5. Computed: 基于其他响应式数据计算得出,并具有缓存机制
  6. Watch: 侦听响应式数据的变化并执行回调函数

这套系统通过精确的依赖收集和高效的更新触发机制,实现了精准的响应式更新,避免了不必要的计算和渲染,从而提升了应用性能。

通过逐行解析这些核心源码,我们可以更深入地理解 Vue 3 响应式系统的实现原理,这对于我们在实际开发中更好地使用 Vue 以及进行性能优化都有很大帮助。


如有不足之处,敬请指正

参考资料:

相关推荐
前端缘梦几秒前
深入理解 Vue 中的虚拟 DOM:原理与实战价值
前端·vue.js·面试
HWL567912 分钟前
pnpm(Performant npm)的安装
前端·vue.js·npm·node.js
柯南952744 分钟前
Vue 3 reactive.ts 源码理解
vue.js
柯南95271 小时前
Vue 3 Ref 源码解析
vue.js
小高0071 小时前
面试官:npm run build 到底干了什么?从 package.json 到 dist 的 7 步拆解
前端·javascript·vue.js
JayceM2 小时前
Vue中v-show与v-if的区别
前端·javascript·vue.js
HWL56792 小时前
“preinstall“: “npx only-allow pnpm“
运维·服务器·前端·javascript·vue.js
秃头小傻蛋3 小时前
Vue 项目中条件加载组件导致 CSS 样式丢失问题解决方案
前端·vue.js
复苏季风3 小时前
vite里把markdown文件渲染成vue组件
vue.js·markdown
streaker3033 小时前
Vue3 + TSX 封装 el-table:还原 Antd 风格的 Columns 配置
vue.js·element