Vue3系列 - 响应式系统的核心:reactive和ref
响应式系统的核心:reactive和ref
Vue3的响应式系统是整个框架的核心,它通过reactive和ref两个主要API实现数据的响应式处理。在Vue2.7中,这些API是基于Vue2的getter/setter实现的,而非Vue3中的Proxy。
reactive的实现原理
reactive函数用于将一个对象转换为响应式对象。让我们看看它的实现:
export function reactive(target) {
makeReactive(target, false)
return target
}
function makeReactive(target, shallow) {
// 如果尝试观察一个只读代理,返回只读版本
if (!isReadonly(target)) {
// 开发环境下的警告...
const ob = observe(
target,
shallow,
isServerRendering()
)
// 更多检查和警告...
}
}这里的关键是observe函数,它是Vue2响应式系统的核心,会为对象创建一个Observer实例,通过Object.defineProperty为对象的每个属性定义getter和setter,从而实现依赖收集和变更通知。
与Vue3不同的是,Vue2.7中的reactive直接修改原始对象,而不是创建一个Proxy:
// 在Vue2.7中为true,在Vue3中为false
reactive(foo) === fooref的实现原理
ref函数用于创建一个包含单一值的响应式引用:
function createRef(rawValue, shallow) {
if (isRef(rawValue)) {
return rawValue
}
const ref = {}
def(ref, RefFlag, true) // 标记为ref
def(ref, ReactiveFlags.IS_SHALLOW, shallow)
def(
ref,
'dep',
defineReactive(ref, 'value', rawValue, null, shallow, isServerRendering())
)
return ref
}ref创建了一个带有value属性的对象,通过defineReactive使这个属性变成响应式的。当我们访问或修改.value属性时,就会触发依赖收集或通知更新。
为什么需要ref?
在JavaScript中,原始类型(如数字、字符串)是按值传递的,无法通过对象属性的getter/setter追踪变化。ref通过将值包装在一个对象中,利用对象的响应式特性来追踪原始值的变化。
总结
Vue2.7中的响应式系统虽然基于Vue2的实现,但提供了与Vue3类似的API,使开发者可以逐步迁移到Vue3的编程风格。理解reactive和ref的实现原理,有助于我们更好地使用Vue的响应式系统,避免常见的陷阱。