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

关于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()。

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页