前言:家人们,大家好!今天分享一篇文章给大家!要是文章对你有帮助,激发了你的灵感,
求个收藏 + 关注啦~后续还有超多惊喜,别错过!
目录
一、引言
二、ref 的源码解析
2.1 基本使用回顾
2.2 源码实现
源码解释
三、reactive 的源码解析
3.1 基本使用回顾
3.2 源码实现
源码解释
四、ref 和 reactive 的区别与联系
4.1 区别
4.2 联系
五、总结
在 Vue 3 里,ref
和 reactive
是构建响应式系统的关键部分。它们为开发者提供了便捷的途径来创建响应式数据,使得数据变化时能自动更新 DOM。本文会深入探究 ref
和 reactive
的源码,以揭示其实现原理。
在正式分析源码前,先回顾下 ref
的基本使用方式:
{{ count }}
在 Vue 3 的源码中,ref
函数的实现如下:
function ref(value?: unknown) {
return createRef(value, false);
}
function createRef(rawValue: unknown, shallow: boolean) {
if (isRef(rawValue)) {
return rawValue;
}
return new RefImpl(rawValue, shallow);
}
class RefImpl {
private _value: T;
private _rawValue: T;
public readonly __v_isRef = true;
constructor(value: T, public readonly _shallow: boolean) {
this._rawValue = _shallow ? value : toRaw(value);
this._value = _shallow ? value : toReactive(value);
}
get value() {
trackRefValue(this);
return this._value;
}
set value(newVal) {
const useDirectValue = this._shallow || isShallow(newVal) || isReadonly(newVal);
newVal = useDirectValue ? newVal : toRaw(newVal);
if (hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal;
this._value = useDirectValue ? newVal : toReactive(newVal);
triggerRefValue(this, newVal);
}
}
}
ref
函数:它调用 createRef
函数来创建 ref
对象。createRef
函数:先检查传入的值是否已经是 ref
对象,若是则直接返回,否则创建一个 RefImpl
实例。RefImpl
类:
_value
和 _rawValue
:_rawValue
存储原始值,_value
存储响应式的值。__v_isRef
:用于标记这是一个 ref
对象。get value()
:访问 ref
的值时,会调用 trackRefValue
进行依赖收集。set value()
:设置 ref
的值时,会先判断新值是否与旧值不同,若不同则更新 _rawValue
和 _value
,并调用 triggerRefValue
触发依赖更新。
{{ state.message }}
function reactive(target: object) {
if (isReadonly(target)) {
return target;
}
return createReactiveObject(
target,
false,
mutableHandlers,
mutableCollectionHandlers
);
}
function createReactiveObject(
target: Target,
isReadonly: boolean,
baseHandlers: ProxyHandler,
collectionHandlers: ProxyHandler
) {
if (!isObject(target)) {
if (__DEV__) {
console.warn(`value cannot be made reactive: ${String(target)}`);
}
return target;
}
if (target[ReactiveFlags.RAW] && !(isReadonly && target[ReactiveFlags.IS_REACTIVE])) {
return target;
}
const proxy = new Proxy(
target,
targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers
);
return proxy;
}
reactive
函数:先检查目标对象是否为只读对象,若是则直接返回,否则调用 createReactiveObject
函数创建响应式对象。createReactiveObject
函数:
Proxy
创建一个代理对象,根据目标对象的类型选择不同的处理程序。ref
可用于基本数据类型和对象,而 reactive
主要用于对象和数组。ref
的值需通过 .value
属性,而 reactive
对象可直接访问属性。ref
基于 RefImpl
类实现,reactive
基于 Proxy
实现。toRefs
将 reactive
对象转换为多个 ref
对象。通过对 ref
和 reactive
源码的深入分析,我们了解到它们的实现原理。ref
借助 RefImpl
类和 getter/setter
进行依赖收集和触发更新,reactive
则利用 Proxy
对对象的属性访问和修改进行拦截。理解这些源码有助于我们更好地运用 ref
和 reactive
,避免常见的错误,从而构建出高效、稳定的 Vue 3 应用。
到这里,这篇文章就和大家说再见啦!我的过往文章里还藏着许多干货,感兴趣的话也可以点击我的主页看看,下面的文章也很精彩,可别错过。创作这篇内容花费了不少心血,要是它帮你解决了问题,或者带来了启发,就多多支持下 “码上前端” 吧~要是想转载,麻烦一定注明本文链接,感谢大家!