Vue 3 Ref 源码解析

本文档将逐行解析 Vue 3 中 ref.ts 文件的源码实现,深入理解 Vue 3 的响应式系统中 ref 的工作原理。

文件头部导入部分

typescript 复制代码
import {
  type IfAny,
  hasChanged,
  isArray,
  isFunction,
  isObject,
} from '@vue/shared'
import { Dep, getDepFromReactive } from './dep'
import {
  type Builtin,
  type ShallowReactiveMarker,
  isProxy,
  isReactive,
  isReadonly,
  isShallow,
  toRaw,
  toReactive,
} from './reactive'
import type { ComputedRef, WritableComputedRef } from './computed'
import { ReactiveFlags, TrackOpTypes, TriggerOpTypes } from './constants'
import { warn } from './warning'

导入部分引入了多个工具函数和类型定义:

  • @vue/shared 导入通用工具函数和类型
  • dep.ts 导入依赖追踪相关类
  • reactive.ts 导入响应式系统核心函数
  • computed.ts 导入计算属性相关类型
  • constants.ts 导入常量枚举
  • warning.ts 导入警告函数
typescript 复制代码
declare const RefSymbol: unique symbol
export declare const RawSymbol: unique symbol

声明了两个唯一的 symbol 类型,用于类型系统中的标识符。RefSymbol 用于区分 Ref 对象,而 RawSymbol 在这里重新声明,可能用于标识原始值。

Ref 接口定义

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

定义了 Ref 接口,它具有以下特征:

  1. 有一个 value 属性,具有 getter 和 setter
  2. 使用 RefSymbol 作为类型区分标识符,这样可以在运行时检查一个对象是否为 Ref

isRef 函数

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 属性是否为 true 来判断。

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 函数,第二个参数 false 表示创建的是深度响应式 ref。

ShallowRef 相关类型和函数

typescript 复制代码
declare const ShallowRefMarker: unique symbol

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

声明了 ShallowRefMarker symbol 并定义了 ShallowRef 类型,它是 Ref 的扩展,添加了 ShallowRefMarker 标记。

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 函数创建一个浅层响应式的 ref 对象。与 ref 不同,它只对 .value 的赋值操作是响应式的,而对值内部属性的修改不是响应式的。

createRef 函数

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

createRef 是创建 ref 的内部函数:

  1. 如果传入的值已经是 ref,则直接返回
  2. 否则创建一个新的 RefImpl 实例

RefImpl 类

typescript 复制代码
/**
 * @internal
 */
class RefImpl<T = any> {
  _value: T
  private _rawValue: T

  dep: Dep = new Dep()

  public readonly [ReactiveFlags.IS_REF] = true
  public readonly [ReactiveFlags.IS_SHALLOW]: boolean = false

  constructor(value: T, isShallow: boolean) {
    this._rawValue = isShallow ? value : toRaw(value)
    this._value = isShallow ? value : toReactive(value)
    this[ReactiveFlags.IS_SHALLOW] = isShallow
  }

RefImpl 是 Ref 的具体实现类:

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

typescript 复制代码
  get value() {
    if (__DEV__) {
      this.dep.track({
        target: this,
        type: TrackOpTypes.GET,
        key: 'value',
      })
    } else {
      this.dep.track()
    }
    return this._value
  }

value 的 getter 方法:

  • 在开发环境下,会跟踪详细的调试信息
  • 在生产环境下,简化依赖追踪
  • 返回 _value
typescript 复制代码
  set value(newValue) {
    const oldValue = this._rawValue
    const useDirectValue =
      this[ReactiveFlags.IS_SHALLOW] ||
      isShallow(newValue) ||
      isReadonly(newValue)
    newValue = useDirectValue ? newValue : toRaw(newValue)
    if (hasChanged(newValue, oldValue)) {
      this._rawValue = newValue
      this._value = useDirectValue ? newValue : toReactive(newValue)
      if (__DEV__) {
        this.dep.trigger({
          target: this,
          type: TriggerOpTypes.SET,
          key: 'value',
          newValue,
          oldValue,
        })
      } else {
        this.dep.trigger()
      }
    }
  }
}

value 的 setter 方法:

  1. 获取旧值
  2. 判断是否直接使用新值(浅层响应式、新值是浅层或只读)
  3. 如果值发生变化,更新 _rawValue_value
  4. 触发依赖更新

triggerRef 函数

typescript 复制代码
/**
 * Force trigger effects that depends on a shallow ref. This is typically used
 * after making deep mutations to the inner value of a shallow ref.
 *
 * @example
 * ```js
 * const shallow = shallowRef({
 *   greet: 'Hello, world'
 * })
 *
 * // Logs "Hello, world" once for the first run-through
 * watchEffect(() => {
 *   console.log(shallow.value.greet)
 * })
 *
 * // This won't trigger the effect because the ref is shallow
 * shallow.value.greet = 'Hello, universe'
 *
 * // Logs "Hello, universe"
 * triggerRef(shallow)
 * ```
 *
 * @param ref - The ref whose tied effects shall be executed.
 * @see {@link https://vuejs.org/api/reactivity-advanced.html#triggerref}
 */
export function triggerRef(ref: Ref): void {
  // ref may be an instance of ObjectRefImpl
  if ((ref as unknown as RefImpl).dep) {
    if (__DEV__) {
      ;(ref as unknown as RefImpl).dep.trigger({
        target: ref,
        type: TriggerOpTypes.SET,
        key: 'value',
        newValue: (ref as unknown as RefImpl)._value,
      })
    } else {
      ;(ref as unknown as RefImpl).dep.trigger()
    }
  }
}

triggerRef 函数用于手动触发浅层 ref 的依赖更新,通常在修改了浅层 ref 内部属性后使用。

类型定义

typescript 复制代码
export type MaybeRef<T = any> =
  | T
  | Ref<T>
  | ShallowRef<T>
  | WritableComputedRef<T>

export type MaybeRefOrGetter<T = any> = MaybeRef<T> | ComputedRef<T> | (() => T)

定义了两个常用的类型别名:

  • MaybeRef 表示可能是 ref 也可能不是的值
  • MaybeRefOrGetter 表示可能是 ref、只读计算属性或 getter 函数的值

unref 函数

typescript 复制代码
/**
 * Returns the inner value if the argument is a ref, otherwise return the
 * argument itself. This is a sugar function for
 * `val = isRef(val) ? val.value : val`.
 *
 * @example
 * ```js
 * function useFoo(x: number | Ref<number>) {
 *   const unwrapped = unref(x)
 *   // unwrapped is guaranteed to be number now
 * }
 * ```
 *
 * @param ref - Ref or plain value to be converted into the plain value.
 * @see {@link https://vuejs.org/api/reactivity-utilities.html#unref}
 */
export function unref<T>(ref: MaybeRef<T> | ComputedRef<T>): T {
  return isRef(ref) ? ref.value : ref
}

unref 函数是 isRef(val) ? val.value : val 的语法糖,用于获取 ref 的值或直接返回非 ref 值。

toValue 函数

typescript 复制代码
/**
 * Normalizes values / refs / getters to values.
 * This is similar to {@link unref}, except that it also normalizes getters.
 * If the argument is a getter, it will be invoked and its return value will
 * be returned.
 *
 * @example
 * ```js
 * toValue(1) // 1
 * toValue(ref(1)) // 1
 * toValue(() => 1) // 1
 * ```
 *
 * @param source - A getter, an existing ref, or a non-function value.
 * @see {@link https://vuejs.org/api/reactivity-utilities.html#tovalue}
 */
export function toValue<T>(source: MaybeRefOrGetter<T>): T {
  return isFunction(source) ? source() : unref(source)
}

toValue 函数扩展了 unref 的功能,除了处理 ref 外还能处理 getter 函数。

proxyRefs 函数

typescript 复制代码
const shallowUnwrapHandlers: ProxyHandler<any> = {
  get: (target, key, receiver) =>
    key === ReactiveFlags.RAW
      ? target
      : unref(Reflect.get(target, key, receiver)),
  set: (target, key, value, receiver) => {
    const oldValue = target[key]
    if (isRef(oldValue) && !isRef(value)) {
      oldValue.value = value
      return true
    } else {
      return Reflect.set(target, key, value, receiver)
    }
  },
}

定义了用于 proxyRefs 的代理处理器:

  • get 操作:如果是 RAW 标志则返回目标对象,否则对获取的值进行 unref 操作
  • set 操作:如果旧值是 ref 且新值不是 ref,则更新旧值 ref 的 value,否则直接设置属性
typescript 复制代码
/**
 * Returns a proxy for the given object that shallowly unwraps properties that
 * are refs. If the object already is reactive, it's returned as-is. If not, a
 * new reactive proxy is created.
 *
 * @param objectWithRefs - Either an already-reactive object or a simple object
 * that contains refs.
 */
export function proxyRefs<T extends object>(
  objectWithRefs: T,
): ShallowUnwrapRef<T> {
  return isReactive(objectWithRefs)
    ? objectWithRefs
    : new Proxy(objectWithRefs, shallowUnwrapHandlers)
}

proxyRefs 函数创建一个代理对象,该对象会自动解包属性中的 ref:

  • 如果对象已经是响应式的,直接返回
  • 否则创建一个使用 shallowUnwrapHandlers 处理器的代理

CustomRef 相关实现

typescript 复制代码
export type CustomRefFactory<T> = (
  track: () => void,
  trigger: () => void,
) => {
  get: () => T
  set: (value: T) => void
}

定义了 CustomRefFactory 类型,这是一个工厂函数类型,接收 track 和 trigger 函数作为参数,返回包含 get 和 set 方法的对象。

typescript 复制代码
class CustomRefImpl<T> {
  public dep: Dep

  private readonly _get: ReturnType<CustomRefFactory<T>>['get']
  private readonly _set: ReturnType<CustomRefFactory<T>>['set']

  public readonly [ReactiveFlags.IS_REF] = true

  public _value: T = undefined!

  constructor(factory: CustomRefFactory<T>) {
    const dep = (this.dep = new Dep())
    const { get, set } = factory(dep.track.bind(dep), dep.trigger.bind(dep))
    this._get = get
    this._set = set
  }

  get value() {
    return (this._value = this._get())
  }

  set value(newVal) {
    this._set(newVal)
  }
}

CustomRefImpl 是自定义 ref 的实现:

  • 通过工厂函数获取自定义的 get 和 set 方法
  • get 方法执行时会调用自定义的 get 方法并更新 _value
  • set 方法执行时会调用自定义的 set 方法
typescript 复制代码
/**
 * Creates a customized ref with explicit control over its dependency tracking
 * and updates triggering.
 *
 * @param factory - The function that receives the `track` and `trigger` callbacks.
 * @see {@link https://vuejs.org/api/reactivity-advanced.html#customref}
 */
export function customRef<T>(factory: CustomRefFactory<T>): Ref<T> {
  return new CustomRefImpl(factory) as any
}

customRef 函数用于创建自定义 ref,允许用户显式控制依赖追踪和更新触发。

toRefs 函数

typescript 复制代码
export type ToRefs<T = any> = {
  [K in keyof T]: ToRef<T[K]>
}

ToRefs 类型定义了将对象的所有属性转换为 ref 的类型。

typescript 复制代码
/**
 * Converts a reactive object to a plain object where each property of the
 * resulting object is a ref pointing to the corresponding property of the
 * original object. Each individual ref is created using {@link toRef}.
 *
 * @param object - Reactive object to be made into an object of linked refs.
 * @see {@link https://vuejs.org/api/reactivity-utilities.html#torefs}
 */
export function toRefs<T extends object>(object: T): ToRefs<T> {
  if (__DEV__ && !isProxy(object)) {
    warn(`toRefs() expects a reactive object but received a plain one.`)
  }
  const ret: any = isArray(object) ? new Array(object.length) : {}
  for (const key in object) {
    ret[key] = propertyToRef(object, key)
  }
  return ret
}

toRefs 函数将响应式对象的所有属性转换为 ref:

  • 开发环境下会检查对象是否为响应式对象
  • 根据对象是否为数组创建对应的返回容器
  • 遍历对象属性,使用 propertyToRef 将每个属性转换为 ref

ObjectRefImpl 类

typescript 复制代码
class ObjectRefImpl<T extends object, K extends keyof T> {
  public readonly [ReactiveFlags.IS_REF] = true
  public _value: T[K] = undefined!

  constructor(
    private readonly _object: T,
    private readonly _key: K,
    private readonly _defaultValue?: T[K],
  ) {}

  get value() {
    const val = this._object[this._key]
    return (this._value = val === undefined ? this._defaultValue! : val)
  }

  set value(newVal) {
    this._object[this._key] = newVal
  }

  get dep(): Dep | undefined {
    return getDepFromReactive(toRaw(this._object), this._key)
  }
}

ObjectRefImpl 是属性 ref 的实现:

  • 创建一个指向对象特定属性的 ref
  • get 操作返回对象对应属性的值
  • set 操作更新对象对应属性的值
  • dep 从原始对象的响应式系统中获取

GetterRefImpl 类

typescript 复制代码
class GetterRefImpl<T> {
  public readonly [ReactiveFlags.IS_REF] = true
  public readonly [ReactiveFlags.IS_READONLY] = true
  public _value: T = undefined!

  constructor(private readonly _getter: () => T) {}
  get value() {
    return (this._value = this._getter())
  }
}

GetterRefImpl 是 getter ref 的实现:

  • 创建一个只读的 ref,其值来自 getter 函数
  • 只有 get 操作,没有 set 操作

toRef 函数

typescript 复制代码
export type ToRef<T> = IfAny<T, Ref<T>, [T] extends [Ref] ? T : Ref<T>>

ToRef 类型定义了将值转换为 ref 的类型。

typescript 复制代码
/**
 * Used to normalize values / refs / getters into refs.
 *
 * @example
 * ```js
 * // returns existing refs as-is
 * toRef(existingRef)
 *
 * // creates a ref that calls the getter on .value access
 * toRef(() => props.foo)
 *
 * // creates normal refs from non-function values
 * // equivalent to ref(1)
 * toRef(1)
 * ```
 *
 * Can also be used to create a ref for a property on a source reactive object.
 * The created ref is synced with its source property: mutating the source
 * property will update the ref, and vice-versa.
 *
 * @example
 * ```js
 * const state = reactive({
 *   foo: 1,
 *   bar: 2
 * })
 *
 * const fooRef = toRef(state, 'foo')
 *
 * // mutating the ref updates the original
 * fooRef.value++
 * console.log(state.foo) // 2
 *
 * // mutating the original also updates the ref
 * state.foo++
 * console.log(fooRef.value) // 3
 * ```
 *
 * @param source - A getter, an existing ref, a non-function value, or a
 *                 reactive object to create a property ref from.
 * @param [key] - (optional) Name of the property in the reactive object.
 * @see {@link https://vuejs.org/api/reactivity-utilities.html#toref}
 */
export function toRef<T>(
  value: T,
): T extends () => infer R
  ? Readonly<Ref<R>>
  : T extends Ref
    ? T
    : Ref<UnwrapRef<T>>
export function toRef<T extends object, K extends keyof T>(
  object: T,
  key: K,
): ToRef<T[K]>
export function toRef<T extends object, K extends keyof T>(
  object: T,
  key: K,
  defaultValue: T[K],
): ToRef<Exclude<T[K], undefined>>
export function toRef(
  source: Record<string, any> | MaybeRef,
  key?: string,
  defaultValue?: unknown,
): Ref {
  if (isRef(source)) {
    return source
  } else if (isFunction(source)) {
    return new GetterRefImpl(source) as any
  } else if (isObject(source) && arguments.length > 1) {
    return propertyToRef(source, key!, defaultValue)
  } else {
    return ref(source)
  }
}

toRef 函数用于将值标准化为 ref:

  1. 如果是 ref,直接返回
  2. 如果是函数,创建 GetterRefImpl
  3. 如果是对象且提供了 key,使用 propertyToRef
  4. 否则创建普通 ref
typescript 复制代码
function propertyToRef(
  source: Record<string, any>,
  key: string,
  defaultValue?: unknown,
) {
  const val = source[key]
  return isRef(val)
    ? val
    : (new ObjectRefImpl(source, key, defaultValue) as any)
}

propertyToRef 函数用于创建属性 ref:

  • 如果属性值已经是 ref,直接返回
  • 否则创建 ObjectRefImpl 实例

类型定义

typescript 复制代码
/**
 * This is a special exported interface for other packages to declare
 * additional types that should bail out for ref unwrapping. For example
 * \@vue/runtime-dom can declare it like so in its d.ts:
 *
 * ``` ts
 * declare module '@vue/reactivity' {
 *   export interface RefUnwrapBailTypes {
 *     runtimeDOMBailTypes: Node | Window
 *   }
 * }
 * ```
 */
export interface RefUnwrapBailTypes {}

export type ShallowUnwrapRef<T> = {
  [K in keyof T]: DistributeRef<T[K]>
}

type DistributeRef<T> = T extends Ref<infer V, unknown> ? V : T

定义了 RefUnwrapBailTypes 接口和相关类型,允许其他包声明不应解包的类型。

typescript 复制代码
export type UnwrapRef<T> =
  T extends ShallowRef<infer V, unknown>
    ? V
    : T extends Ref<infer V, unknown>
      ? UnwrapRefSimple<V>
      : UnwrapRefSimple<T>

UnwrapRef 类型用于解包 ref 类型,获取其内部值的类型。

typescript 复制代码
export type UnwrapRefSimple<T> = T extends
  | Builtin
  | Ref
  | RefUnwrapBailTypes[keyof RefUnwrapBailTypes]
  | { [RawSymbol]?: true }
  ? T
  : T extends Map<infer K, infer V>
    ? Map<K, UnwrapRefSimple<V>> & UnwrapRef<Omit<T, keyof Map<any, any>>>
    : T extends WeakMap<infer K, infer V>
      ? WeakMap<K, UnwrapRefSimple<V>> &
          UnwrapRef<Omit<T, keyof WeakMap<any, any>>>
      : T extends Set<infer V>
        ? Set<UnwrapRefSimple<V>> & UnwrapRef<Omit<T, keyof Set<any>>>
        : T extends WeakSet<infer V>
          ? WeakSet<UnwrapRefSimple<V>> & UnwrapRef<Omit<T, keyof WeakSet<any>>>
          : T extends ReadonlyArray<any>
            ? { [K in keyof T]: UnwrapRefSimple<T[K]> }
            : T extends object & { [ShallowReactiveMarker]?: never }
              ? {
                  [P in keyof T]: P extends symbol ? T[P] : UnwrapRef<T[P]>
                }
              : T

UnwrapRefSimple 类型递归解包复杂类型的 ref,处理各种内置对象类型和自定义对象类型。

TypeScript 语法解析

这个文件中使用了许多高级 TypeScript 语法和特性,下面是详细解析:

1. 泛型 (Generics)

typescript 复制代码
export interface Ref<T = any, S = T> {
  get value(): T
  set value(_: S)
  // ...
}

这里定义了 Ref 接口,使用了泛型参数 T 和 S,其中 S 默认值为 T。这允许 Ref 对象的 getter 和 setter 可以有不同的类型。

2. 条件类型 (Conditional Types)

typescript 复制代码
export function ref<T>(
  value: T,
): [T] extends [Ref] ? IfAny<T, Ref<T>, T> : Ref<UnwrapRef<T>, UnwrapRef<T> | T>

这个函数签名使用了条件类型,根据 T 是否继承自 Ref 来决定返回类型。如果 T 是 Ref 类型,则根据 IfAny 工具类型决定返回 Ref 还是 T;否则返回 Ref<UnwrapRef, UnwrapRef | T>。

3. 映射类型 (Mapped Types)

typescript 复制代码
export type ToRefs<T = any> = {
  [K in keyof T]: ToRef<T[K]>
}

这里使用了映射类型,将对象 T 的每个属性 K 映射为 ToRef<T[K]> 类型。

4. infer 关键字

typescript 复制代码
T extends () => infer R
  ? Readonly<Ref<R>>
  : T extends Ref
    ? T
    : Ref<UnwrapRef<T>>

在条件类型中使用 infer 关键字可以从函数类型中推断出返回值类型 R。

5. 模板字面量类型 (Template Literal Types)

虽然在这个文件中没有直接使用,但 Vue 项目中广泛使用了这种类型,用于创建更精确的类型。

6. 类型守卫 (Type Guards)

typescript 复制代码
export function isRef<T>(r: Ref<T> | unknown): r is Ref<T>

使用 r is Ref<T> 语法创建类型守卫函数,这在 TypeScript 中用于运行时类型检查。

7. 索引类型 (Indexed Types)

typescript 复制代码
class ObjectRefImpl<T extends object, K extends keyof T> {
  // ...
  get value() {
    const val = this._object[this._key]  // 使用索引类型访问属性
    return (this._value = val === undefined ? this._defaultValue! : val)
  }
}

通过 keyof TT[K] 语法实现对对象属性的类型安全访问。

8. 装饰器和访问修饰符

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

  dep: Dep = new Dep()

  public readonly [ReactiveFlags.IS_REF] = true
  public readonly [ReactiveFlags.IS_SHALLOW]: boolean = false
  // ...
}

使用了 public、private 和 readonly 等访问修饰符和属性初始化器。

9. 类型断言

typescript 复制代码
return new CustomRefImpl(factory) as any

在适当的时候使用类型断言来处理复杂的类型关系。

10. 联合类型和交叉类型

typescript 复制代码
export type MaybeRef<T = any> =
  | T
  | Ref<T>
  | ShallowRef<T>
  | WritableComputedRef<T>

使用联合类型表示一个值可能是多种类型中的一种。

11. 实用工具类型

文件中使用了多种 TypeScript 内置工具类型,如:

  • Partial<T> - 将 T 中的所有属性变为可选
  • Readonly<T> - 将 T 中的所有属性变为只读
  • Pick<T, K> - 从 T 中选择一组属性 K
  • Omit<T, K> - 从 T 中排除属性 K

12. 唯一符号 (unique symbol)

typescript 复制代码
declare const RefSymbol: unique symbol

使用 unique symbol 创建全局唯一的符号,用于类型系统中的唯一标识。

13. 模块增强 (Module Augmentation)

typescript 复制代码
/**
 * This is a special exported interface for other packages to declare
 * additional types that should bail out for ref unwrapping.
 */
export interface RefUnwrapBailTypes {}

定义了可以被其他模块扩展的接口,这是一种模块增强的模式。

14. 函数重载

typescript 复制代码
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)
}

通过函数重载提供多种调用方式,增强函数的类型安全性。

总结

这个文件实现了 Vue 3 响应式系统中的 ref 相关功能,包括:

  1. 基础的 refshallowRef 创建函数
  2. isRefunreftoReftoRefs 等工具函数
  3. triggerRefcustomRef 高级功能
  4. proxyRefstoValue 便利函数
  5. 复杂的类型系统支持 ref 的类型推导和解包
相关推荐
CDwenhuohuo31 分钟前
优惠券组件直接用 uview plus
前端·javascript·vue.js
AI砖家1 小时前
Vue3组件传参大全,各种传参方式的对比
前端·javascript·vue.js
爱怪笑的小杰杰2 小时前
Leaflet 高性能大数据量图圆:彻底解决缩放/拖拽偏移问题
大数据·前端·vue.js·贴图
笔优站长3 小时前
vue-sign-canvas v2 重构复盘:从 Vue 2 签名板到 Vue 3 + TypeScript 组件库
前端·vue.js
Aolith3 小时前
事件驱动设计:我如何为校园论坛实现消息通知功能
前端·vue.js
代码煮茶3 小时前
Vue3 Mock 数据实战 | 用 Mockjs + vite-plugin-mock 搭建前端独立开发环境
javascript·vue.js
糯米团子7495 小时前
vue知识点复习
前端·vue.js
范同学~5 小时前
多个表单如何用element ui 校验
javascript·vue.js·ui
xuankuxiaoyao6 小时前
vue.js 设计与开发 ---路由
前端·javascript·vue.js
_xaboy7 小时前
开源Vue组件FormCreate通过 JSON 生成AntdvNext表单
vue.js·开源·json