一遍看懂! Vue3 watch的onCleanup和onWatcherCleanup

watch中还有onCleanup这种东西?!

 有的兄弟,有的。

 你熟悉的watch其实长这样。

 我们看看官方对它的解释:

看完之后是不是感觉似懂非懂的?

一句话概括,其实onCleanup解决的是,watch中的副作用函数多次执行时,任务顺序的问题。

我们来看一个开发案例:

 const r1 = ref('haluo') //假设这个是一个输入框的绑定值

 // 接下来我们模拟一个请求

 let timer=3000;

 function getData(timer) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(timer);
            }, timer);
        });
 }

 // 我们监听值的变化,变一次发送一次请求
 watch(
        r1,
        async (newValue, oldValue, onCleanup) => {
            timer -= 1000;
            let r = await getData(timer);
            console.log('-->', r);
        },
        {
            flush: "sync",
        }
  );

 // 应该很好理解,每执行一次请求,timer减少1s

 // 然后假设我们触发了两次值的变化

 setTimeout(() => {
        r1.value = '1'
        r1.value = '2'
 }, 1000);

timer初始值是3000,每次减少1000。

按照我们正常的理解,这两次执行的结果是不是应该是:2000 >>> 1000

但实际呢?

结果是 1000 >>> 2000

这怎么能行呢,我们要的肯定是最新一次的结果,也就是1000噻。

所以这时候onCleanup就产生作用了。

// 现在我们加入onCleanup

watch(
        r1,
        async (newValue, oldValue, onCleanup) => {
            // 我们初始化一个值flag
            let flag = true;
            timer -= 1000;
            // 在onCleanup中去改变它的值,记得onCleanup要在await前面
            onCleanup(() => {
                flag = false;
            })
            let r = await getData(timer);
            // 根据flag的值取判断是否渲染
            if (flag) {
                console.log('-->', r);
            }
        },
        {
            flush: "sync",
        }
);

这时候再看控制台的值,就是我们想要的结果了。

 

有点神奇是吧,是怎么实现的呢?

其实说白了,就是一个闭包,接下来我们不用onCleanup,换个方法改造一下watch的回调函数。

 let queue = [];
 watch(
        r1,
        async (newValue, oldValue) => {
            let flag = true;
            timer -= 1000;
            // 现在我们不用onCleanup 而是在外面新建了一个数组queue
            // 把queue中的函数取出来挨个执行一遍
            for (let i = 0; i < queue.length; i++) {
                queue[i]();
            }
            // 每次执行,我们为queue推入一个函数,把flag变成false
            queue.push(() => (flag = false));
            let r = await getData(timer);
            if (flag) {
                console.log('-->', r);
            }
        },
        {
            flush: "sync",
        }
 );

看到没有,效果一样

不太理解?我们推导一下执行过程。

核心就是,每次函数执行,都会开辟新的执行环境,这里面的flag都是独立的,同时又保留了上一个flag的清理方法,将它变成false。

这就是onCleanup的实现原理,其实理解之后就非常简单了。

源码里面其实就是把你传到onCleanup的fn存起来了,每次执行的时候就把上一次的fn执行一下。

至于vue3.5的 onWatcherCleanup Api,想必聪明的你也知道怎么回事了吧。

学废了吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值