用法
在下次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的原理是什么样子的
-
将所有的nextTick的回调函数放进flashCallbacks里面
-
通过timerFunc将回调函数封装为microtask或者macirotask
-
如果没有正在执行回调函数,则执行timerfunc函数,即执行flashCallBacks
nextTick是如何监听到函数的完成的
因为在一个task执行完成后,会进行渲染dom这个微任务,timerFunc将flushCallbacks封装为了微任务/宏任务,那么把此任务放在渲染dom后面,就可以取到真实的DOM元素了。
因为兼容问题,nextTick做了从microtask到macrotask的降级,降级的顺序为
首选promise,如果不支持的话,macrotask降级的方案依次是:setImmediate、MessageChannel、setTimeout.