浅谈Vue.nextTick 的实现方法(2)
只关注主流程queueNextTick函数把我们传入的() => { // todo... } 推入了callbacks内
if (typeof Promise !== 'undefined' && isNative(Promise)) {
var p = Promise.resolve()
var logError = err => { console.error(err) }
timerFunc = () => {
p.then(nextTickHandler).catch(logError) // 重点
}
} else if ('!isIE MutationObserver') {
var counter = 1
var observer = new MutationObserver(nextTickHandler) // 重点
var textNode = document.createTextNode(string(conter))
observer.observe(textNode, {
characterData: true
})
timerFunc = () => {
counter = (counter + 1) % 2
textNode.data = String(counter)
}
} else {
timerFunc = () => {
setTimeout(nextTickHandler, 0) // 重点
}
}
这一段我们可以看到标注的三个点表明在不同浏览器环境下使用Promise, MutationObserver或setTimeout(fn, 0) 来执行nextTickHandler
function nextTickHandler () {
pending = false
const copies = callbacks.slice(0) // 复制
callbacks.length = 0 // 清空
for (let i = 0; i < copies.length; i++) {
copies[i]() // 逐个执行
}
}
nextTickHandler就是把我们之前放入callbacks的 () => { // todo... } 在当前tasks内执行。
写一个简单的nextTick
源码可能比较绕,我们自己写一段简单的nextTick
const simpleNextTick = (function () {
let callbacks = []
let timerFunc
return function queueNextTick (cb) {
callbacks.push(() => { // 给callbacks 推入cb()
cb()
})
timerFunc = () => {
return Promise.resolve().then(() => {
const fn = callbacks.shift()
fn()
})
}
timerFunc() // 执行timerFunc,返回到是一个Promise
}
})()
simpleNextTick(() => {
setTimeout(console.log, 3000, 'nextTick')
})
我们可以从这里看出nextTick的原理就是返回出一个Promise,而我们todo的代码在这个Promise中执行,现在我们还可以继续简化
const simpleNextTick = (function () {
return function queueNextTick (cb) {
timerFunc = () => {
return Promise.resolve().then(() => {
cb()
})
}
timerFunc()
}
})()
simpleNextTick(() => {
setTimeout(console.log, 3000, 'nextTick')
})
直接写成这样。
const simpleNextTick = function queueNextTick (cb) {
timerFunc = () => {
return Promise.resolve().then(() => {
cb()
})
}
timerFunc()
}
simpleNextTick(() => {
setTimeout(console.log, 3000, 'nextTick')
})
这次我们把自执行函数也简化掉
const simpleNextTick = function queueNextTick (cb) {
return Promise.resolve().then(cb)
}
simpleNextTick(() => {
setTimeout(console.log, 3000, 'nextTick')
})
内容版权声明:除非注明,否则皆为本站原创文章。
