• 作者:老汪软件技巧
  • 发表时间:2024-10-13 11:03
  • 浏览量:

1.ref

在 Vue 3 中,ref 的实现主要依赖于 Proxy 对象和 Dep(依赖)机制来追踪依赖关系和触发更新。不过,对于基本数据类型,ref 并不会直接使用 Proxy,因为 Proxy 需要一个对象作为目标,而基本数据类型本身不是对象。相反,ref 会创建一个包含 value 属性的对象来包装基本数据类型,从而使其能够被响应式系统所管理。

下面是一个简化的 ref 源码分析:

源码位置

ref 的定义位于 @vue/reactivity 包中的 src/ref.ts 文件中。

源码分析

// @vue/reactivity/src/ref.ts
import { isObject, hasOwn, isFunction } from '@vue/shared'
import { track, trigger } from './effect'
import { ReactiveFlags, Target, TargetWithMemo } from './reactive'
import { EffectScope, recordEffectScope } from './effectScope'
import { toRaw, toReactive } from './reactive'
export interface Ref {
  value: T
  __v_isRef: true
}
export function ref(value: T): Ref<UnwrapRef> {
  return createRef(value, false)
}
function createRef(rawValue: unknown, shallow: boolean): Ref<unknown> {
  if (isRef(rawValue)) {
    return rawValue
  }
  const r: Ref<any> = {
    __v_isRef: true,
    _rawValue: rawValue,
    _value: shallow ? rawValue : toReactive(rawValue),
    get value() {
      track(r, TrackOpTypes.GET, 'value')
      return r._value
    },
    set value(newVal) {
      if (hasChanged(r._rawValue, newVal)) {
        r._rawValue = newVal
        r._value = shallow ? newVal : toReactive(newVal)
        trigger(r, TriggerOpTypes.SET, 'value', newVal)
      }
    }
  }
  return r
}

关键点解析

createRef 函数:

get value 方法:

set value 方法:

小结

通过这种方式,Vue 3 能够有效地管理基本数据类型的响应式变化。

2.toReactive

引用数据类型作用__引用类型数据成员

在 Vue 3 中,toReactive 函数用于将一个值转换为响应式对象。toReactive 主要通过 reactive 函数来实现,而 reactive 函数的核心是使用 Proxy 对象来拦截对对象属性的访问和修改,从而实现响应式。

源码位置

toReactive 和 reactive 的定义位于 @vue/reactivity 包中的 src/reactive.ts 文件中。

源码分析toReactive 函数

// @vue/reactivity/src/reactive.ts
import { isObject, hasOwn, isFunction } from '@vue/shared'
import { reactiveMap, readonlyMap } from './baseHandlers'
import { ReactiveFlags, Target, TargetWithMemo } from './reactive'
import { EffectScope, recordEffectScope } from './effectScope'
import { toRaw, toReactive } from './reactive'
export function toReactive(value: T): T {
  return isObject(value) ? reactive(value) : value
}
export function reactiveextends object>(target: T): UnwrapNestedRefs {
  // 如果目标已经是响应式对象,直接返回
  if (isReactive(target)) {
    return target
  }
  // 如果目标是只读对象,返回只读版本
  if (isReadonly(target)) {
    return readonly(target)
  }
  // 创建响应式代理
  return createReactiveObject(
    target,
    false,
    mutableHandlers,
    mutableCollectionHandlers,
    reactiveMap
  )
}

createReactiveObject 函数

function createReactiveObject(
  target: Target,
  isShallow: boolean,
  baseHandlers: ProxyHandler<any>,
  collectionHandlers: ProxyHandler<any>,
  proxyMap: WeakMapany>
) {
  if (!isObject(target)) {
    if (__DEV__) {
      console.warn(`value cannot be made reactive: ${String(target)}`)
    }
    return target
  }
  // 查找缓存的代理对象
  const existingProxy = proxyMap.get(target)
  if (existingProxy) {
    return existingProxy
  }
  // 创建新的代理对象
  const proxy = new Proxy(target, collectionHandlers)
  proxyMap.set(target, proxy)
  return proxy
}

关键点解析

toReactive 函数:

reactive 函数:

createReactiveObject 函数:

处理基本数据类型和引用数据类型

引用数据类型:

小结

通过这种方式,Vue 3 能够高效地管理和追踪复杂数据结构的变化,同时保持对基本数据类型的简洁处理。


上一条查看详情 +行业模板|DataEase电子商务大屏模板推荐
下一条 查看详情 +没有了