深入解析Vue3中ref与reactive的区别及源码实现
深入解析Vue3中ref与reactive的区别及源码实现
前言
Vue3带来了全新的响应式系统,其中ref
和reactive
是最常用的两个API。本文将从基础使用、核心区别到源码实现,由浅入深地分析这两个API。
一、基础使用
1. ref
import { ref } from vueconst count = ref(0)
console.log(count.value) // 0
count.value++
2. reactive
import { reactive } from vueconst state = reactive({ count: 0 })
console.log(state.count) // 0
state.count++
二、核心区别
1. 数据类型
ref
可以包装任意值类型(原始值、对象)reactive
只能处理对象类型
2. 访问方式
ref
需要通过.value
访问reactive
直接访问属性
3. 解构行为
ref
解构后仍保持响应性reactive
解构后会丢失响应性
4. 性能考量
ref
更适合独立的基本类型值reactive
更适合复杂对象
三、源码实现解析
1. ref实现原理
// packages/reactivity/src/ref.ts
class RefImpl<T> {private _value: Tprivate _rawValue: Tpublic dep?: Dep = undefinedpublic readonly __v_isRef = trueconstructor(value: T) {this._rawValue = valuethis._value = convert(value)}get value() {trackRefValue(this)return this._value}set value(newVal) {newVal = convert(newVal)if (hasChanged(newVal, this._rawValue)) {this._rawValue = newValthis._value = newValtriggerRefValue(this)}}
}
2. reactive实现原理
// packages/reactivity/src/reactive.ts
function reactive(target: object) {if (isReadonly(target)) {return target}return createReactiveObject(target,false,mutableHandlers,mutableCollectionHandlers)
}function createReactiveObject(target: Target,isReadonly: boolean,baseHandlers: ProxyHandler<any>,collectionHandlers: ProxyHandler<any>
) {// 使用Proxy进行代理const proxy = new Proxy(target,targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers)proxyMap.set(target, proxy)return proxy
}
四、最佳实践
- 基本类型优先使用
ref
- 复杂对象使用
reactive
- 组合使用时注意解构问题
- 大型项目考虑使用
toRefs
保持响应性
五、总结
ref
和reactive
都是Vue3响应式系统的核心,理解它们的区别和实现原理,能帮助我们更好地使用Vue3开发应用。