vue的ref实现
Vue 的 ref 实现原理
Vue 中的 ref 是一个用于响应式数据管理的核心 API,它可以用于基本类型或对象类型的响应式包装。以下是其实现的关键点:
基本类型与对象的处理
对于基本类型(如字符串、数字等),ref 会将其包装为一个带有 value 属性的对象。对于对象类型,ref 会调用 reactive 进行深层响应式处理。
const count = ref(0) // { value: 0 }
const obj = ref({ foo: 1 }) // 等价于 reactive({ foo: 1 })
源码核心逻辑
在 Vue 3 源码中,ref 的实现主要依赖于 RefImpl 类:

class RefImpl<T> {
private _value: T
private _rawValue: T
public readonly __v_isRef = true
constructor(value: T) {
this._rawValue = value
this._value = convert(value)
}
get value() {
track(this, TrackOpTypes.GET, 'value')
return this._value
}
set value(newVal) {
if (hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal
this._value = convert(newVal)
trigger(this, TriggerOpTypes.SET, 'value', newVal)
}
}
}
function convert(value) {
return isObject(value) ? reactive(value) : value
}
模板中的自动解包
在模板中使用 ref 时,Vue 会自动解包 .value,无需手动访问:
<template>
<div>{{ count }}</div> <!-- 自动解包,无需写 count.value -->
</template>
ref 与 reactive 的区别
ref 通过 .value 访问数据,适合处理基本类型或需要替换整个对象引用的情况。reactive 直接返回代理对象,适合处理复杂对象结构但无法直接替换整个引用。

自定义 ref
可以通过 customRef 创建具有自定义逻辑的 ref:
function useDebouncedRef(value, delay = 200) {
return customRef((track, trigger) => {
let timeout
return {
get() {
track()
return value
},
set(newValue) {
clearTimeout(timeout)
timeout = setTimeout(() => {
value = newValue
trigger()
}, delay)
}
}
})
}
组件 ref
当 ref 用于组件时,会指向组件实例:
<template>
<ChildComponent ref="child" />
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
setup() {
const child = ref(null)
onMounted(() => {
console.log(child.value) // 子组件实例
})
return { child }
}
}
</script>






