Vue3 nextTick 源码分析

Vue3 nextTick 源码分析

vue版本

3.2.37

前言

在之前的Vue2分析中,提到了Vue2的nextTick是维护了一个callbacks数组,每次更新过程中只插入一个微任务,执行放在callbacks数组中的回调。

而Vue3不同,Vue3的nextTick和Promise基本没什么区别,set过程的更新看似也不再依赖,nextTick进行。仅仅只是将创建一个resovled状态的Promise,将传入的函数放入回调中罢了。以下是vue3的nextTick源码:

const resolvedPromise = /*#__PURE__*/ Promise.resolve();
let currentFlushPromise = null;
function nextTick(fn) {
   
    const p = currentFlushPromise || resolvedPromise;
    return fn ? p.then(this ? fn.bind(this) : fn) : p;
}

正因为如此,同样的代码,在Vue2和Vue3中会有不同的表现。参考以下代码:

Promise.resolve().then(()=>{
   
                console.log('开始的Promise回调')
            })
            this.$nextTick(()=>{
   
                console.log('第一次nextTick的回调')
            })
            Promise.resolve().then(()=>{
   
                console.log('修改数据之前的Promise回调')
            })
            this.name = 'kirito' // 这里进行赋值操作
            Promise.resolve().then(()=>{
   
                console.log('修改数据之后的Promise回调')
            })
            this.$nextTick(()=>{
   
                console.log('最后的nextTick的回调')
            })

以上代码的运行结果,在Vue2中是:

开始的Promise回调
第一次nextTick的回调
最后的nextTick的回调
修改数据之前的Promise回调
修改数据之后的Promise回调

只要调用了nextTick或者对数据进行了变更,那么放在之后的Promise回调,一定是排在后面执行的。

而同样的代码:

        const name = ref('yuuki')
        const test2 = () => {
   
            Promise.resolve().then(()=>{
   
                console.log('开始的Promise回调')
            })
            nextTick(()=>{
   
                console.log('第一次nextTick的回调')
            })
            Promise.resolve().then(()=>{
   
                console.log('修改数据之前的Promise回调')
            }) 
            name.value = 'kirito'  // 这里进行赋值操作
            Promise.resolve().then(()=>{
   
                console.log('修改数据之后的Promise回调')
            })
            nextTick(()=>{
   
                console.log('最后的nextTick的回调')
            })
        }

在Vue3中的执行结果是:

开始的Promise回调
第一次nextTick的回调
修改数据之前的Promise回调
修改数据之后的Promise回调
最后的nextTick的回调

看上去完全是按照Promise加入微任务队列的逻辑,一次nextTick就是插入一个微任务队列,不维护callbacks数组。

实例分析

上述示例代码,赋值操作如果稍稍改变一下位置,又会与预想的输出截然不同:

        const name = ref('yuuki')
        const age = ref(18)
        const test2 = () => {
   
            Promise.resolve().then(()=>{
   
                console.log('开始的Promise回调')
            })
            name.value = 'kirito'  // 这里进行赋值操作
            nextTick(()=>{
   
                console.log('第一次nextTick的回调')
            })
            Promise.resolve().then(()=>{
   
                console.log('修改数据之前的Promise回调')
            }) 
            Promise.resolve().then(()=>{
   
                console.log('修改数据之后的Promise回调')
            })
            nextTick(()=>{
   
                console.log('最后的nextTick的回调')
            })
        }

以上的代码,执行了之后输出变成:

开始的Promise回调
修改数据之前
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值