Vue3 ref 模块设计拆解
ref 模块的核心目标:
👉 让基本类型也具备响应式能力
👉 提供统一的“值容器抽象”
整体由 4 个核心实现类组成:
1. RefImpl —— 标准 ref
用于 ref / shallowRef
特点:
- 内部持有 Dep 依赖集合
- 通过
.value的 getter/setter 建立响应式 - 基本类型通过 getter/setter 劫持
- 对象类型自动转为 reactive
所以 ref 的本质是:
外层 getter/setter + 内层 Proxy
当访问:
ref.value→ 触发 getter/setter 响应式ref.value.xxx→ 触发 Proxy 响应式
setter 内部使用 Object.is 判断变化:
- 区分 +0 / -0
- 正确处理 NaN
- 避免无意义 trigger
这是性能与边界值兼顾的设计。
2. CustomRefImpl —— 自定义 ref
用于 customRef
开发者手动控制:
- track
- trigger
适合做:
- 防抖
- 节流
- 缓存
- 异步数据
本质是开放响应式调度权。
3. ObjectRefImpl —— 对象属性 ref
用于:
toRef(obj, 'key')
设计亮点:
👉 不创建新状态
👉 代理原对象属性
它:
- 保存原对象引用
- 读写直接操作原对象
- 依赖从原对象获取
这保证:
toRef 是“视图”,不是“拷贝”
始终与源对象同步。
4. GetterRefImpl —— getter 函数 ref
用于:
toRef(() => x)
特点:
- 只读
- 每次访问执行 getter
- 依赖由 getter 内部自动收集
它没有自己的 Dep:
依赖来自 getter 访问的响应式数据
工厂函数体系
ref 模块提供一整套转换工具:
ref / shallowRef
创建标准 ref
toRef
把多种类型统一包装成 ref:
- 已是 ref → 原样返回
- getter → GetterRefImpl
- 对象属性 → ObjectRefImpl
- 普通值 → RefImpl
统一抽象入口。
toRefs
把 reactive 对象拆成多个 ref:
reactive → ref 视图层
注意:
toRefs 不会让普通对象变成响应式
它是拆解工具,不是 reactive 工具。
如果目标不是 reactive:
只是创建包装壳
proxyRefs
为对象创建代理:
- 访问时自动 unref
- 赋值时自动写回 ref.value
这是模板自动解包的基础机制。
因为 setup 编译后本质是:
返回一个对象
proxyRefs 负责让模板写法更自然。
工具函数
unref
解包 ref
toValue (3.3+)
组合式函数统一入参:
- ref → unref
- function → 执行
减少样板代码。
isRef
通过标记:
__v_isRef === true
判断 ref 类型。
triggerRef
手动触发 ref 更新。
用于 shallowRef 或手动控制场景。