前言
本文是 Vue3 源码实战专栏的第 6 篇。
第三篇 完善effect功能 中实现了stop
方法,本篇文章完善stop
方法,并通过断点调试来完整解析整个流程。
修改单测
在原本的基础上,修改effect
中stop
测试用例。
it("stop", () => {
let dummy;
const obj = reactive({ prop: 1 });
const runner = effect(() => {
dummy = obj.prop;
});
obj.prop = 2;
expect(dummy).toBe(2);
stop(runner);
// obj.prop = 3;
obj.prop++;
expect(dummy).toBe(2);
// stopped effect should still be manually callable
runner();
expect(dummy).toBe(3);
});
运行单测yarn test effect

报错分析
简单分析一下报错的原因。
obj.prop++
可以理解成obj.prop = obj.prop + 1
,存在get
和set
两个操作,触发get
操作会重新收集依赖,导致stop
中cleanupEffect
方法删除所有effect
失效。
实现
知道了根本原因是先触发get
操作重新执行了effect
中函数,也就是调用了track
方法,那需要完善的逻辑应该这个方法入手。我们可以定义一个全局变量shouldTrack
来判断是否需要进行track
操作。
let reactiveEffect;
let shouldTrack; // 定义
export function track(target, key) {
...
if(!shouldTrack) return // 直接return不进行依赖收集
if (!reactiveEffect) return;
dep.add(reactiveEffect);
reactiveEffect.deps.push(dep);
}
进行赋值的时候触发set
操作,执行trigger
函数,最终调用的是 Class 类ReactiveEffect
中run
方法。run
方法中原本是直接返回了入参函数的执行结果,这里就需要判断一下stop
的情况,可以依据active
来判断。
如果是调用了stop
方法之后,active
赋值为false
,这时候直接返回fn
;
如果没有调用stop
方法,先将shouldTrack
设为true
,表示可以进行track
调用,然后执行fn
,并将执行结果返回,但是在返回之前需要重置操作,将shouldTrack
设置成false
,因为如果在遇到stop
之后,run
函数中会直接return
,不会将shouldTrack
设为true
,那在track
时,就会走!shouldTrack
直接return
不再收集依赖。
run() {
if (!this.active) {
return this._fn();
}
shouldTrack = true;
reactiveEffect = this;
const result = this._fn();
shouldTrack = false;
return result;
}
重构
track
中shouldTrack
和reactiveEffect
的边界判断,可以提到track
函数体内顶部,单独封装一个函数合成这两个判断。
依赖收集这儿可以优化的点,当dep
中存在的reactiveEffect
就不再重复收集了。
export function track(target, key) {
if (!isTracking()) return;
...
if (dep.has(reactiveEffect)) return;
dep.add(reactiveEffect);
reactiveEffect.deps.push(dep);
}
function isTracking() {
return shouldTrack && reactiveEffect !== undefined;
}
调试
修改一下单测,用更简单的单测来通过调试清晰看一下上述流程。
it("stop", () => {
let dummy;
const obj = reactive({ prop: 1 });
const runner = effect(() => {
dummy = obj.prop;
});
stop(runner);
obj.prop++;
expect(dummy).toBe(1);
});
这里通过一个视频讲解来更形象的了解。
原文始发于微信公众号(前端一起学):优化effect stop功能,附全流程断点调试视频
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/191296.html