核心方法和实现
1.ref()函数
export function ref(value?: unknown) {
return createRef(value, false)
}
- 创建一个响应式引用
- 内部通过 RefImpl 类实现
- 可以保障任意类型的值
RefImpl类的核心实现:
class RefImpl<T = any> {
_value: T
private _rawValue: T
dep: Dep = new Dep()
get value() {
this.dep.track() // 依赖收集
return this._value
}
set value(newValue) {
if (hasChanged(newValue, this._rawValue)) {
this._rawValue = newValue
this._value = toReactive(newValue)
this.dep.trigger() // 触发更新
}
}
}
setter 函数
- 参数和初始处理:
set value(newValue) {
const oldValue = this._rawValue
-
函数接收一个新值newValue
-
首先保存当前的原始值到oldValue
- 判断是否需要直接使用新值:
const useDirectValue =
this[ReactiveFlags.IS_SHALLOW] ||
isShallow(newValue) ||
isReadonly(newValue)
-
在三种情况下会直接使用新值而不做深层响应式转换:
-
当前ref是浅层ref (shallowRef)
-
新值本身是浅层响应式对象
-
新值是只读对象
-
- 值的处理:
newValue = useDirectValue ? newValue : toRaw(newValue)
-
如果useDirectValue为true,直接使用新值
-
否则,通过toRaw获取新值的原始值(去除响应式包装)
- 更新逻辑:
if (hasChanged(newValue, oldValue)) {
this._rawValue = newValue
this._value = useDirectValue ? newValue : toReactive(newValue)
-
只有当新值和旧值不同时才进行更新
-
更新_rawValue为新的原始值
-
更新_value,如果是直接使用就用newValue,否则将其转换为响应式对象
- 触发依赖更新:
if (__DEV__) {
this.dep.trigger({
target: this,
type: TriggerOpTypes.SET,
key: 'value',
newValue,
oldValue,
})
} else {
this.dep.trigger()
}
-
在开发环境下,触发依赖时会携带更详细的信息
-
生产环境下直接触发依赖更新
这个setter的主要作用是:
-
维护ref的原始值和响应式值
-
处理浅层响应式的情况
-
确保值的变化时才触发更新
-
触发依赖追踪系统进行更新
主要特性
- 响应式包装
-
通过 .value 访问和修改值
-
自动的依赖收集和更新触发
-
对象类型会被自动转换为响应式对象
- 浅层响应式
-
shallowRef() - 只对顶层属性做响应式转换
-
适用于大型数据结构的性能优化
- 工具函数
-
isRef() - 检查是否是ref对象
-
unref() - 如果是ref则返回内部值,否则返回原值
-
toRefs() - 将响应式对象转换为普通对象,其中每个属性都是对应的ref
- 自定义 ref
-
customRef() - 允许自定义依赖收集和触发更新的逻辑
-
提供更灵活的响应式控制