nextTick 实现原理
为什么需要?
使用案例:
//
dialogTableVisible(newValue, oldValue) {
if (newValue) {
this.$nextTick(() => {
this.toggleSelection(this.tableDataList)
})
}
}
如何做到在dom重新渲染后执行下一次操作?
从浏览器的事件执行流程可以看出,如何做到nextTick 可以使用浏览器的这个特性实现。
// 纯函数
import { noop } from 'shared/util'
// 处理异常的函数
import { handleError } from './error'
export let isUsingMicroTask = false
// 任务队列
const callbacks = []
// 任务队列的flag
let pending = false
// 执行任务队列方法
function flushCallbacks () {
pending = false
const copies = callbacks.slice(0)
callbacks.length = 0
for (let i = 0; i < copies.length; i++) {
copies[i]()
}
}
let timerFunc
if (typeof Promise !== 'undefined') {
const p = Promise.resolve()
timerFunc = () => {
p.then(flushCallbacks)
}
isUsingMicroTask = true
} else {
// Fallback to setTimeout.
timerFunc = () => {
setTimeout(flushCallbacks, 0)
}
}
// 在使用nextTick 时将待执行待函数放入到执行的队尾
export function nextTick (cb?: Function, ctx?: Object) {
// 实现一个promise 提供给业务 所以在使用 this.$nextTick 时可以使用 await 等待其异步执行,不仅仅可以使用 nextTick(cb)的形式
let _resolve
// 将函数push至队列中
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 => {
_resolve = resolve
})
}
}
以上代码有删减,vue中因为需要兼容多平台,写了web weex nodejs 的兼容写法,但是逻辑一样,主流程也一样,其中的精髓在于使用浏览器的setTimeout 微任务的特性,实现nexttick的队列。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!