往往
往往
Published on 2025-05-30 / 0 Visits
0
0

Vue3源码理解 - reactivity

源码仓库

https://github.com/vuejs/core/tree/v3.2.37

reactivity响应式系统源码位置

packages/reactivity

主入口文件

packages/reactivity/src/index.ts

export {
  ref, // 创建一个响应式引用
  shallowRef, // 创建一个浅层响应式引用
  isRef, // 检查一个值是否是响应式引用
  toRef, // 将一个响应式对象的属性转换为响应式引用
  toRefs, // 将一个响应式对象的所有属性转换为响应式引用
  unref, // 获取响应式引用的值
  proxyRefs, // 代理响应式引用,使其可以直接访问值
  customRef, // 创建自定义的响应式引用
  triggerRef, // 触发响应式引用的更新
  Ref, // 响应式引用的类型
  ToRef, // toRef函数的返回类型
  ToRefs, // toRefs函数的返回类型
  UnwrapRef, // 解包响应式引用的类型
  ShallowRef, // 浅层响应式引用的类型
  ShallowUnwrapRef, // 解包浅层响应式引用的类型
  RefUnwrapBailTypes, // 解包响应式引用时需要跳过的类型
  CustomRefFactory // 自定义响应式引用工厂的类型
} from './ref'

// 导出响应式对象相关功能
export {
  reactive, // 将一个普通对象转换为响应式对象
  readonly, // 将一个普通对象转换为只读的响应式对象
  isReactive, // 检查一个对象是否是响应式对象
  isReadonly, // 检查一个对象是否是只读的响应式对象
  isShallow, // 检查一个对象是否是浅层响应式对象
  isProxy, // 检查一个对象是否是代理对象
  shallowReactive, // 创建一个浅层响应式对象
  shallowReadonly, // 创建一个浅层只读的响应式对象
  markRaw, // 标记一个对象为非响应式
  toRaw, // 获取一个响应式对象的原始对象
  ReactiveFlags, // 响应式对象的特殊标志
  DeepReadonly, // 深层只读的响应式对象类型
  ShallowReactive, // 浅层响应式对象类型
  UnwrapNestedRefs // 解包嵌套响应式引用的类型
} from './reactive'

// 导出计算属性相关功能
export {
  computed, // 创建一个计算属性
  ComputedRef, // 计算属性的类型
  WritableComputedRef, // 可写的计算属性的类型
  WritableComputedOptions, // 可写的计算属性的选项
  ComputedGetter, // 计算属性的getter函数类型
  ComputedSetter // 计算属性的setter函数类型
} from './computed'

// 导出延迟计算属性功能
export { deferredComputed } from './deferredComputed'

// 导出副作用相关功能
export {
  effect, // 创建一个副作用函数
  stop, // 停止一个副作用函数的自动执行
  trigger, // 触发副作用函数的执行
  track, // 跟踪副作用函数的依赖
  enableTracking, // 启用副作用函数的依赖跟踪
  pauseTracking, // 暂停副作用函数的依赖跟踪
  resetTracking, // 重置副作用函数的依赖跟踪
  ITERATE_KEY, // 迭代操作的特殊键
  ReactiveEffect, // 副作用函数的类型
  ReactiveEffectRunner, // 副作用函数的执行器类型
  ReactiveEffectOptions, // 副作用函数的选项
  EffectScheduler, // 副作用函数的调度器类型
  DebuggerOptions, // 调试选项
  DebuggerEvent, // 调试事件
  DebuggerEventExtraInfo // 调试事件的额外信息
} from './effect'

// 导出副作用作用域相关功能
export {
  effectScope, // 创建一个副作用作用域
  EffectScope, // 副作用作用域的类型
  getCurrentScope, // 获取当前的副作用作用域
  onScopeDispose // 注册一个在副作用作用域销毁时执行的回调
} from './effectScope'

// 导出操作类型
export { TrackOpTypes, TriggerOpTypes } from './operations'

./reactive

源码:

./reactive源码入手,源码如下:

// 引入工具函数和类型
import { isObject, toRawType, def } from '@vue/shared'
import {
  mutableHandlers,
  readonlyHandlers,
  shallowReactiveHandlers,
  shallowReadonlyHandlers
} from './baseHandlers'
import {
  mutableCollectionHandlers,
  readonlyCollectionHandlers,
  shallowCollectionHandlers,
  shallowReadonlyCollectionHandlers
} from './collectionHandlers'
import type { UnwrapRefSimple, Ref, RawSymbol } from './ref'

// 定义响应式对象的内部标志
export const enum ReactiveFlags {
  SKIP = '__v_skip', // 跳过响应式转换的标志
  IS_REACTIVE = '__v_isReactive', // 是否是响应式对象
  IS_READONLY = '__v_isReadonly', // 是否是只读对象
  IS_SHALLOW = '__v_isShallow', // 是否是浅层响应式
  RAW = '__v_raw' // 原始对象的引用
}

// 定义响应式对象的类型
export interface Target {
  [ReactiveFlags.SKIP]?: boolean
  [ReactiveFlags.IS_REACTIVE]?: boolean
  [ReactiveFlags.IS_READONLY]?: boolean
  [ReactiveFlags.IS_SHALLOW]?: boolean
  [ReactiveFlags.RAW]?: any
}

// 定义存储响应式对象的WeakMap
// weakmap只能以对象为键,创建弱引用的map,当没有强引用指向其中的对象后,垃圾处理器将会随时清除其,能有效防止内存泄漏
export const reactiveMap = new WeakMap<Target, any>()
export const shallowReactiveMap = new WeakMap<Target, any>()
export const readonlyMap = new WeakMap<Target, any>()
export const shallowReadonlyMap = new WeakMap<Target, any>()

// 定义目标类型的枚举
const enum TargetType {
  INVALID = 0, // 无效类型
  COMMON = 1, // 普通对象或数组
  COLLECTION = 2 // 集合类型(Map、Set等)
}

// 根据原始类型返回目标类型
function targetTypeMap(rawType: string) {
  switch (rawType) {
    case 'Object':
    case 'Array':
      return TargetType.COMMON
    case 'Map':
    case 'Set':
    case 'WeakMap':
    case 'WeakSet':
      return TargetType.COLLECTION
    default:
      return TargetType.INVALID
  }
}

// 获取目标类型
// 主要目的是判断目标对象是否可以转化为响应式对象
function getTargetType(value: Target) {
  return value[ReactiveFlags.SKIP] || !Object.isExtensible(value)    
    ? TargetType.INVALID
    : targetTypeMap(toRawType(value))
// 如果响应式对象被标记为SKIP或对象不可扩展(Object.isExtensible检查对象是否可扩展)
// 否则返回TargetType.INVALID否则根据目标对象原始类型返回目标类型
}

// 定义类型,用于解包嵌套的响应式引用
export type UnwrapNestedRefs<T> = T extends Ref ? T : UnwrapRefSimple<T>

// 创建一个响应式对象的函数
export function reactive<T extends object>(target: T): UnwrapNestedRefs<T>
export function reactive(target: object) {
  // 如果目标已经是只读的响应式对象,直接返回
  if (isReadonly(target)) {
    return target
  }
  // 调用createReactiveObject创建响应式对象
  return createReactiveObject(
    target,
    false,
    mutableHandlers,
    mutableCollectionHandlers,
    reactiveMap
  )
}

// 定义浅层响应式的标记
export declare const ShallowReactiveMarker: unique symbol

// 定义浅层响应式的类型
export type ShallowReactive<T> = T & { [ShallowReactiveMarker]?: true }

// 创建一个浅层响应式对象的函数
export function shallowReactive<T extends object>(target: T): ShallowReactive<T> {
  return createReactiveObject(
    target,
    false,
    shallowReactiveHandlers,
    shallowCollectionHandlers,
    shallowReactiveMap
  )
}

// 定义深层只读类型的类型
export type DeepReadonly<T> = T extends Builtin
  ? T
  : T extends Map<infer K, infer V>
  ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>
  : T extends ReadonlyMap<infer K, infer V>
  ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>
  : T extends WeakMap<infer K, infer V>
  ? WeakMap<DeepReadonly<K>, DeepReadonly<V>>
  : T extends Set<infer U>
  ? ReadonlySet<DeepReadonly<U>>
  : T extends ReadonlySet<infer U>
  ? ReadonlySet<DeepReadonly<U>>
  : T extends WeakSet<infer U>
  ? WeakSet<DeepReadonly<U>>
  : T extends Promise<infer U>
  ? Promise<DeepReadonly<U>>
  : T extends Ref<infer U>
  ? Readonly<Ref<DeepReadonly<U>>>
  : T extends {}
  ? { readonly [K in keyof T]: DeepReadonly<T[K]> }
  : Readonly<T>

// 创建一个只读响应式对象的函数
export function readonly<T extends object>(target: T): DeepReadonly<UnwrapNestedRefs<T>> {
  return createReactiveObject(
    target,
    true,
    readonlyHandlers,
    readonlyCollectionHandlers,
    readonlyMap
  )
}

// 创建一个浅层只读响应式对象的函数
export function shallowReadonly<T extends object>(target: T): Readonly<T> {
  return createReactiveObject(
    target,
    true,
    shallowReadonlyHandlers,
    shallowReadonlyCollectionHandlers,
    shallowReadonlyMap
  )
}

// 创建响应式对象的通用函数
function createReactiveObject(
  target: Target,
  isReadonly: boolean,
  baseHandlers: ProxyHandler<any>,
  collectionHandlers: ProxyHandler<any>,
  proxyMap: WeakMap<Target, any>
) {
  // 如果目标不是对象,直接返回
  if (!isObject(target)) {
    if (__DEV__) {
      console.warn(`value cannot be made reactive: ${String(target)}`)
    }
    return target
  }
  // 如果目标已经是代理对象,直接返回
  if (
    target[ReactiveFlags.RAW] &&
    !(isReadonly && target[ReactiveFlags.IS_REACTIVE])
  ) {
    return target
  }
  // 如果目标已经有对应的代理对象,直接返回
  const existingProxy = proxyMap.get(target)
  if (existingProxy) {
    return existingProxy
  }
  // 只有特定的值类型可以被观察
  const targetType = getTargetType(target)
  if (targetType === TargetType.INVALID) {
    return target
  }
  // 创建代理对象
  const proxy = new Proxy(
    target,
    targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers
  )
  // 将代理对象存储到WeakMap中
  proxyMap.set(target, proxy)
  return proxy
}

// 检查一个值是否是响应式对象
export function isReactive(value: unknown): boolean {
  if (isReadonly(value)) {
    return isReactive((value as Target)[ReactiveFlags.RAW])
  }
  return !!(value && (value as Target)[ReactiveFlags.IS_REACTIVE])
}

// 检查一个值是否是只读响应式对象
export function isReadonly(value: unknown): boolean {
  return !!(value && (value as Target)[ReactiveFlags.IS_READONLY])
}

// 检查一个值是否是浅层响应式对象
export function isShallow(value: unknown): boolean {
  return !!(value && (value as Target)[ReactiveFlags.IS_SHALLOW])
}

// 检查一个值是否是代理对象
export function isProxy(value: unknown): boolean {
  return isReactive(value) || isReadonly(value)
}

// 获取响应式对象的原始对象
export function toRaw<T>(observed: T): T {
  const raw = observed && (observed as Target)[ReactiveFlags.RAW]
  return raw ? toRaw(raw) : observed
}

// 标记一个对象为非响应式
export function markRaw<T extends object>(value: T): T & { [RawSymbol]?: true } {
  def(value, ReactiveFlags.SKIP, true)
  return value
}

// 将一个值转换为响应式对象
export const toReactive = <T extends unknown>(value: T): T =>
  isObject(value) ? reactive(value) : value

// 将一个值转换为只读响应式对象
export const toReadonly = <T extends unknown>(value: T): T =>
  isObject(value) ? readonly(value as Record<any, any>) : value
最主要函数:createReactiveObject
function createReactiveObject(        // 传入五个属性,区分创建不同的响应式对象
  target: Target,  // 目标对象
  isReadonly: boolean, //是否只读
  baseHandlers: ProxyHandler<any>, // 使用什么处理器函数来处理普通对象
  collectionHandlers: ProxyHandler<any>, // 使用什么处理器函数来处理集合对象(map、set)
  proxyMap: WeakMap<Target, any>  // 将返回的Proxy对象存储在哪一张weakmap表里,用作缓存,有效减少相同响应式对象重复构建
) {
  // 如果目标不是对象,直接返回
  if (!isObject(target)) {
    if (__DEV__) {
      console.warn(`value cannot be made reactive: ${String(target)}`)
    }
    return target
  }
  // 如果目标已经是响应式对象,直接返回
  if (
    target[ReactiveFlags.RAW] &&
    !(isReadonly && target[ReactiveFlags.IS_REACTIVE])
  ) {
    return target
  }
  // 如果在相应表里已经有对应的响应式对象,直接返回表中对象
  const existingProxy = proxyMap.get(target)
  if (existingProxy) {
    return existingProxy
  }
  // 如果是无效类型直接返回
  const targetType = getTargetType(target)
  if (targetType === TargetType.INVALID) {
    return target
  }
  // 创建代理对象,如果是普通对象,使用baseHandlers,如果是集合对象,使用collectionHandlers
  const proxy = new Proxy(
    target,
    targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers
  )
  // 将代理对象存储到相应的WeakMap中
  proxyMap.set(target, proxy)
  return proxy
}

./ref

源码:
import {
  activeEffect, // 当前激活的 effect
  shouldTrack,  // 是否应该进行依赖收集
  trackEffects, // 跟踪依赖
  triggerEffects // 触发依赖
} from './effect'

// 导入依赖操作类型
import { TrackOpTypes, TriggerOpTypes } from './operations'

// 导入一些工具函数
import { isArray, hasChanged, IfAny } from '@vue/shared'

// 导入与响应式相关的函数和类型
import { isProxy, toRaw, isReactive, toReactive } from './reactive'
import type { ShallowReactiveMarker } from './reactive'

// 导入集合类型
import { CollectionTypes } from './collectionHandlers'

// 导入依赖类
import { createDep, Dep } from './dep'

// 声明一个唯一的符号,用于标记 Ref 类型
declare const RefSymbol: unique symbol

// 定义 Ref 接口,表示一个响应式引用
export declare const RawSymbol: unique symbol

export interface Ref<T = any> {
  value: T // 引用的值
  [RefSymbol]: true // 用于标记这是一个 Ref 类型
}

// 定义 RefBase 类型,表示一个基本的引用类型
type RefBase<T> = {
  dep?: Dep // 依赖集合
  value: T // 引用的值
}

// 跟踪引用值的依赖
export function trackRefValue(ref: RefBase<any>) {
  if (shouldTrack && activeEffect) { // 如果应该跟踪且有激活的 effect
    ref = toRaw(ref) // 获取原始引用
    if (__DEV__) { // 开发模式下
      trackEffects(ref.dep || (ref.dep = createDep()), { // 跟踪依赖
        target: ref, // 目标引用
        type: TrackOpTypes.GET, // 操作类型为 GET
        key: 'value' // 键为 'value'
      })
    } else {
      trackEffects(ref.dep || (ref.dep = createDep())) // 生产模式下直接跟踪依赖
    }
  }
}

// 触发引用值的依赖
export function triggerRefValue(ref: RefBase<any>, newVal?: any) {
  ref = toRaw(ref) // 获取原始引用
  if (ref.dep) { // 如果有依赖集合
    if (__DEV__) { // 开发模式下
      triggerEffects(ref.dep, { // 触发依赖
        target: ref, // 目标引用
        type: TriggerOpTypes.SET, // 操作类型为 SET
        key: 'value', // 键为 'value'
        newValue: newVal // 新值
      })
    } else {
      triggerEffects(ref.dep) // 生产模式下直接触发依赖
    }
  }
}

// 判断一个值是否是 Ref 类型
export function isRef<T>(r: Ref<T> | unknown): r is Ref<T>
export function isRef(r: any): r is Ref {
  return !!(r && r.__v_isRef === true) // 检查是否有 __v_isRef 标志
}

// 创建一个 Ref 对象
export function ref<T extends object>(
  value: T
): [T] extends [Ref] ? T : Ref<UnwrapRef<T>>
export function ref<T>(value: T): Ref<UnwrapRef<T>>
export function ref<T = any>(): Ref<T | undefined>
export function ref(value?: unknown) {
  return createRef(value, false) // 调用 createRef 函数创建 Ref 对象
}

// 声明一个唯一的符号,用于标记浅引用
declare const ShallowRefMarker: unique symbol

// 定义 ShallowRef 类型,表示一个浅响应式引用
export type ShallowRef<T = any> = Ref<T> & { [ShallowRefMarker]?: true }

// 创建一个浅响应式引用
export function shallowRef<T extends object>(
  value: T
): T extends Ref ? T : ShallowRef<T>
export function shallowRef<T>(value: T): ShallowRef<T>
export function shallowRef<T = any>(): ShallowRef<T | undefined>
export function shallowRef(value?: unknown) {
  return createRef(value, true) // 调用 createRef 函数创建浅响应式引用
}

// 创建一个 Ref 对象的实现
function createRef(rawValue: unknown, shallow: boolean) {
  if (isRef(rawValue)) { // 如果已经是 Ref 类型,直接返回
    return rawValue
  }
  return new RefImpl(rawValue, shallow) // 创建一个新的 RefImpl 对象
}

// RefImpl 类的实现
class RefImpl<T> {
  private _value: T // 响应式值
  private _rawValue: T // 原始值

  public dep?: Dep = undefined // 依赖集合
  public readonly __v_isRef = true // 标记为 Ref 类型

  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) {
    newVal = this.__v_isShallow ? newVal : toRaw(newVal) // 获取原始值
    if (hasChanged(newVal, this._rawValue)) { // 如果值发生变化
      this._rawValue = newVal // 更新原始值
      this._value = this.__v_isShallow ? newVal : toReactive(newVal) // 更新响应式值
      triggerRefValue(this, newVal) // 触发依赖
    }
  }
}

// 触发 Ref 的依赖
export function triggerRef(ref: Ref) {
  triggerRefValue(ref, __DEV__ ? ref.value : void 0) // 调用 triggerRefValue 触发依赖
}

// 解包 Ref 的值
export function unref<T>(ref: T | Ref<T>): T {
  return isRef(ref) ? (ref.value as any) : ref // 如果是 Ref 类型,返回其值,否则直接返回
}

// 定义浅解包处理器
const shallowUnwrapHandlers: ProxyHandler<any> = {
  get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)), // 获取值时解包 Ref
  set: (target, key, value, receiver) => {
    const oldValue = target[key]
    if (isRef(oldValue) && !isRef(value)) { // 如果旧值是 Ref,新值不是
      oldValue.value = value // 更新 Ref 的值
      return true
    } else {
      return Reflect.set(target, key, value, receiver) // 否则直接设置值
    }
  }
}

// 创建一个代理,用于解包对象中的 Ref
export function proxyRefs<T extends object>(
  objectWithRefs: T
): ShallowUnwrapRef<T> {
  return isReactive(objectWithRefs) // 如果对象已经是响应式的,直接返回
    ? objectWithRefs
    : new Proxy(objectWithRefs, shallowUnwrapHandlers) // 否则创建代理
}

// 定义自定义 Ref 工厂函数的类型
export type CustomRefFactory<T> = (
  track: () => void,
  trigger: () => void
) => {
  get: () => T
  set: (value: T) => void
}

// 自定义 Ref 的实现
class CustomRefImpl<T> {
  public dep?: Dep = undefined // 依赖集合

  private readonly _get: ReturnType<CustomRefFactory<T>>['get'] // 获取值的函数
  private readonly _set: ReturnType<CustomRefFactory<T>>['set'] // 设置值的函数

  public readonly __v_isRef = true // 标记为 Ref 类型

  constructor(factory: CustomRefFactory<T>) {
    const { get, set } = factory( // 调用工厂函数,传入跟踪和触发函数
      () => trackRefValue(this),
      () => triggerRefValue(this)
    )
    this._get = get // 保存获取值的函数
    this._set = set // 保存设置值的函数
  }

  get value() {
    return this._get() // 调用获取值的函数
  }

  set value(newVal) {
    this._set(newVal) // 调用设置值的函数
  }
}

// 创建一个自定义 Ref
export function customRef<T>(factory: CustomRefFactory<T>): Ref<T> {
  return new CustomRefImpl(factory) as any // 创建 CustomRefImpl 实例
}
最主要函数:createRef
// 创建一个 Ref 对象的实现
function createRef(rawValue: unknown, shallow: boolean) {
  if (isRef(rawValue)) { // 如果已经是 Ref 类型,直接返回
    return rawValue
  }
  return new RefImpl(rawValue, shallow) // 创建一个新的 RefImpl 对象
}

// RefImpl 类的实现
class RefImpl<T> {
  private _value: T // 响应式值
  private _rawValue: T // 原始值

  public dep?: Dep = undefined // 依赖集合
  public readonly __v_isRef = true // 标记为 Ref 类型

  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) {
    newVal = this.__v_isShallow ? newVal : toRaw(newVal) // 获取原始值
    if (hasChanged(newVal, this._rawValue)) { // 如果值发生变化
      this._rawValue = newVal // 更新原始值
      this._value = this.__v_isShallow ? newVal : toReactive(newVal) // 更新响应式值
      triggerRefValue(this, newVal) // 触发依赖
    }
  }
}

为什么通过构造函数来实现ref顶层响应式?

  1. 简单性和易用性ref提供了一种简单的方式来创建响应式数据。通过直接使用value属性,开发者可以轻松地访问和修改数据,而不需要额外的语法或复杂的结构。

  2. 性能优化ref的实现通常是针对特定的框架(如Vue.js)进行了优化,以确保在数据变化时能够高效地更新视图。使用Proxy虽然可以实现响应式,但可能会引入额外的开销,尤其是在处理大量数据或复杂对象时。

  3. 明确的语义ref的设计使得数据的响应式行为非常明确。开发者知道ref对象的value属性是响应式的,而其他属性则不是。这种明确性有助于减少误解和错误。


Comment