ref实现原理vue
ref 的实现原理(Vue 3)
在 Vue 3 中,ref 是响应式系统的核心 API 之一,用于将基本类型或对象转换为响应式引用。其实现依赖于 ES6 的 Proxy 和 getter/setter 机制。
基本类型处理
对于基本类型(如 number、string),ref 会通过一个包装对象实现响应式。内部通过 value 属性访问实际值,触发依赖收集和更新通知:
function ref(value) {
return createRef(value, false);
}
function createRef(rawValue, shallow) {
// 已经是 ref 则直接返回
if (isRef(rawValue)) return rawValue;
return new RefImpl(rawValue, shallow);
}
class RefImpl {
constructor(value, __v_isShallow) {
this.__v_isShallow = __v_isShallow;
this._rawValue = value;
this._value = __v_isShallow ? value : toReactive(value);
this.dep = undefined;
}
get value() {
trackRefValue(this); // 依赖收集
return this._value;
}
set value(newVal) {
if (hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal;
this._value = toReactive(newVal);
triggerRefValue(this); // 触发更新
}
}
}
对象类型处理
当传入对象时,ref 会调用 reactive 进行深层响应式转换。通过 toReactive 函数自动处理:
const toReactive = (value) =>
isObject(value) ? reactive(value) : value;
与 reactive 的区别
-
访问方式
ref需要通过.value访问数据,而reactive直接访问属性。const count = ref(0); count.value++; // 需要 .value const state = reactive({ count: 0 }); state.count++; // 直接访问 -
适用场景
ref适用于基本类型或需要替换整个对象的场景,reactive适用于对象/数组的深层响应式。
模板中的自动解包
在模板中使用 ref 时,Vue 会自动解包,无需手动写 .value:
<template>
<div>{{ count }}</div> <!-- 自动解包 -->
</template>
<script setup>
const count = ref(0);
</script>
依赖收集与触发
-
依赖收集
通过trackRefValue在get value()时记录当前活跃的 effect(如组件的渲染函数)。 -
触发更新
通过triggerRefValue在set value()时通知所有依赖的 effect 重新执行。
源码关键点
-
响应式标记
ref对象通过__v_isRef标记,便于isRef检查。 -
性能优化
多次设置相同值时会通过hasChanged比较,避免不必要的更新触发。 -
浅层
ref
通过shallowRef可创建仅对.value敏感的浅层响应式引用。






