[Vue] ref及其底层原理
在上一篇文章里我描述了reactive响应式的原理,但是vue3不止只有reactive能创建响应式的对象,它还有ref
也能创建响应式对象。
那ref
的响应式原理是与reactive
一样的吗?
先说结论:是的!
我之前一直以为ref是vue2的Object.defineProperty
的实现而且一直被误导了很久,甚至还在某次面试上大言不惭的说ref是基于Object.defineProperty
实现的,现在想来还真是头铁呢!
ref本身其实与reactive并无多大的区别,响应式也是reactive那一套(effect()
、track()
、trigger()
),而设计出ref的原因只是因为reactive必须传入一个引用类型,因为proxy只能代理对象,而像是基础类型什么number
string
bool
啥的它是没法代理的。所以本质上ref只是一层ractive的语法糖,通过包装成.value
的对象进而被Proxy代理。
类似这样的:
function ref(value) {// 把原始值转换为响应式对象(如果是对象)const wrapper = {get value() {track(wrapper, 'value'); // 收集依赖return value;},set value(newVal) {if (newVal !== value) {value = newVal;trigger(wrapper, 'value'); // 触发依赖}}};return wrapper;
}
结论
ref
是 Vue 3 用来让基础类型响应式的语法糖,它的 .value 是响应系统的出口,底层实现并不再使用 Vue 2 的 Object.defineProperty,而是走统一的 Proxy + track/trigger 架构。