vue暴露的全局方法_关于Vue暴露的全局nextTick

本文探讨Vue中全局方法$nextTick的工作原理,通过一个示例解释了其执行顺序与事件循环的关系。代码分析表明,$nextTick的实现利用pending标志避免重复执行,并在事件循环的不同阶段调度任务。在给定的例子中,执行顺序为1、2、'promise'、3,揭示了宏任务和微任务的执行特点。
摘要由CSDN通过智能技术生成

关于Vue暴露的全局nextTick

继续来看下面的这段代码:

{{test}}

tet

var vm = new Vue({

el: '#example',

data: { test: 'begin',

},

methods: { handleClick() {

this.test = 'end';

console.log('1') setTimeout(() => { // macroTask

console.log('3')

}, 0);

Promise.resolve().then(function() { //microTask

console.log('promise!')

})

this.$nextTick(function () {

console.log('2')

})

}

}

})

在Chrome下,这段代码执行的顺序的1、2、promise、3。

可能有同学会以为这是1、promise、2、3,其实是忽略了一个标志位pending。

我们回到nextTick函数return的queueNextTick可以发现:

return function queueNextTick (cb?: Function, ctx?: Object) { let _resolve

/*cb存到callbacks中*/

callbacks.push(() => { if (cb) {

try {

cb.call(ctx)

} catch (e) {

handleError(e, ctx, 'nextTick')

}

} else if (_resolve) {

_resolve(ctx)

}

}) if (!pending) {

pending = true timerFunc()

} if (!cb && typeof Promise !== 'undefined') { return new Promise((resolve, reject) => {

_resolve = resolve

})

}

}

这里面通过对pending的判断来检测是否已经有timerFunc这个函数在事件循环的任务队列等待被执行。如果存在的话,那么是不会再重复执行的。

最后异步执行nextTickHandler时又会把pending置为false。

function nextTickHandler () {

pending = false /*执行所有callback*/

const copies = callbacks.slice(0)

callbacks.length = 0 for (let i = 0; i < copies.length; i++) {

copies[i]()

}

}

所以回到我们的例子:

handleClick() {

this.test = 'end';

console.log('1') setTimeout(() => { // macroTask

console.log('3')

}, 0);

Promise.resolve().then(function() { //microTask

console.log('promise!')

});

this.$nextTick(function () {

console.log('2')

});

}

代码中,this.test = 'end'必然会触发watcher进行视图的重新渲染,而我们在文章的Watcher一节中就已经有提到会调用nextTick函数,一开始pending变量肯定就是false,因此它会被修改为true并且执行timerFunc。之后执行this.

nextTick(fn)只是把传入的fn置入callbacks之中。此时的callbacks有两个function成员,一个是flushSchedulerQueue,另外一个就是this.$nextTick()的回调。

因此,上面这段代码中,在Chrome下,有一个macroTask和两个microTask。一个macroTask就是setTimeout,两个microTask:分别是Vue的timerFunc(其中先后执行flushSchedulerQueue和function() {console.log('2')})、代码中的Promise.resolve().then()。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值