vue.nextTick的原理

294 阅读2分钟

用法

在下次DOM更新循环结束之后执行延迟回调,在修改数据之后立即使用这个方法,获取更新后的DOM

基础知识

setImmediate

原理

异步说明

Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新

在Vue的文档中,说明Vue是异步执行DOM更新的。异步执行的运行机制如下

1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。

时间循环说明

简单来说,Vue在修改数据之后,视图不会立即更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新

例如:

//改变数据
vm.message = 'changed'

//想要立即使用更新后的DOM。这样不行,因为设置message后DOM还没有更新
console.log(vm.$el.textContent) // 并不会得到'changed'

//这样可以,nextTick里面的代码会在DOM更新后执行
Vue.nextTick(function(){
    console.log(vm.$el.textContent) //可以得到'changed'
})

常见面试题

nextTick的原理是什么样子的

  1. 将所有的nextTick的回调函数放进flashCallbacks里面

  2. 通过timerFunc将回调函数封装为microtask或者macirotask

  3. 如果没有正在执行回调函数,则执行timerfunc函数,即执行flashCallBacks

blog.csdn.net/qq_42072086…

nextTick是如何监听到函数的完成的

因为在一个task执行完成后,会进行渲染dom这个微任务,timerFunc将flushCallbacks封装为了微任务/宏任务,那么把此任务放在渲染dom后面,就可以取到真实的DOM元素了。

juejin.cn/post/684490…

因为兼容问题,nextTick做了从microtask到macrotask的降级,降级的顺序为

首选promise,如果不支持的话,macrotask降级的方案依次是:setImmediate、MessageChannel、setTimeout.