vue/core源码中ref源码的js化
起源:
当看见reactivity文件中的ref.ts文件长达五百多的ts代码后,突发奇想想看下转化成js有多少行。
进行转化:
let shouldTrack = true; // Define shouldTrack variable
let activeEffect = null; // Define activeEffect variable
// 定义 ref 函数
function ref(value) {
return createRef(value, false);
}
// 浅的引用 ref
function shallowRef(value) {
return createRef(value, true);
}
// 创造 ref 函数
function createRef(rawValue, shallow) {
// 判断 rawValue 是不是 ref 类型的
if (isRef(rawValue)) {
// 是的话直接 retur
return rawValue;
}
// 不是的话 使用:RefImpl 将其变成ref对象后return出去
return new RefImpl(rawValue, shallow);
}
// 定义 ref的 对象 RefImpl 类
class RefImpl {
constructor(value, isShallow) {
this._rawValue = isShallow ? value : toRaw(value);
this._value = isShallow ? value : toReactive(value);
}
get value() {
trackRefValue(this);
return this._value;
}
set value(newVal) {
const useDirectValue = this.__v_isShallow || 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, DirtyLevels.Dirty, newVal);
}
}
}
function trackRefValue(ref) {
if (shouldTrack && activeEffect) {
ref = toRaw(ref);
trackEffect(
activeEffect,
(ref.dep ??= createDep(
() => (ref.dep = undefined),
ref instanceof ComputedRefImpl ? ref : undefined,
)),
__DEV__
? {
target: ref,
type: TrackOpTypes.GET,
key: 'value',
}
: void 0
);
}
}
function triggerRefValue(ref, dirtyLevel = DirtyLevels.Dirty, newVal) {
ref = toRaw(ref);
const dep = ref.dep;
if (dep) {
triggerEffects(
dep,
dirtyLevel,
__DEV__
? {
target: ref,
type: TriggerOpTypes.SET,
key: 'value',
newValue: newVal,
}
: void 0
);
}
}
// 判断是不是ref
function isRef(r) {
return !!(r && r.__v_isRef === true);
}
function toRaw(observed) {
return observed;
}
function toReactive(value) {
return value;
}
let result = ref(0);
console.log(result);
转化完毕,相信看过源码的小伙伴一经发现,转化前的代码非常臃肿且难以阅读,转化后的代码轻便易于阅读,且能快速在浏览器的控制台调试和实现ref的功能。
最后我们通过打印result可以看到输出了一个RefImpl对象,之后我们通过打印result.value即可获得我们当初传给ref的0
经过测试,发现输出的颜色很淡的values是class类中的get values方法
当传进_value的值的时候,因为构造函数中的get values方法是return的,所以在最后的console中点开values是可以看见: "这里是_values"输出的
将get values函数中return改为console后,打印出来的values就是undefined了,因为没有向外return了
同理,这时候想要学习vue3,通过john.values就可以打印出: "这里是_value"了.
但是感觉下面的_value和value是一个东西,可以用_value统一起来方便看:
class RefImpl {
constructor(value, isShallow) {
this._rawValue = isShallow ? value : toRaw(value);
this._value = isShallow ? value : toReactive(value);
}get value() {
trackRefValue(this);
return this._value;
}set value(newVal) {
const useDirectValue = this.__v_isShallow || 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, DirtyLevels.Dirty, newVal);
}
}
}
上述: get value方法中return的this._value就是constructor中穿进去的value,统一更方便看.
原文地址:https://blog.csdn.net/kuang_nu/article/details/139087553
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!