一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第22天,点击查看活动详情。
nextTick
Vue是异步修改DOM的并且不鼓励开发者直接接触DOM,但有时候业务需要必须对数据更改--刷新后的DOM做相应的处理,这时候就可以使用Vue.nextTick(callback)这个api了
// 修改数据
vm.msg = 'Hello'
// DOM 还没有更新
Vue.nextTick(function () {
// DOM 更新了
})
尽管MVVM框架并不推荐访问DOM,但有时候确实会有这样的需求,尤其是和第三方插件进行配合的 时候,免不了要进行DOM操作。而nextTick就提供了一个桥梁,确保我们操作的是更新后的DOM。
- vue如何检测到DOM更新完毕
能监听到DOM改动的API:MutationObserver
- 理解MutationObserver
MutationObserver是HTML5新增的属性,用于监听DOM修改事件,能够监听到节点的属性、文本内 容、子节点等的改动,是一个功能强大的利器。
//MutationObserver基本用法
var observer = new MutationObserver(function(){
//这里是回调函数
console.log('DOM被修改了!');
});
var article = document.querySelector('article');
observer.observer(article);
理解原理前的准备
首先需要知道事件循环中宏任务和微任务这两个概念
- 常见的宏任务有:script,setTimeout,setInterval,setImmediate,I/O,UIrendering
- 常见的微任务有:process.nextTick(nodejs),Promise.then(),MutationObserver
理解nextTick的原理
Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。
Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部尝试对异步队列使用原生的Promise.then和MessageChannel,如果执行环境不支持,会采用setTimeout(fn, 0)代替。
例如,当你设置vm.someData = 'new value',该组件不会立即重新渲染。当刷新队列时,组件会在事件循环队列清空时的下一个“tick”更新。多数情况我们不需要关心这个过程,但是如果你想在 DOM 状态更新后做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员沿着“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们确实要这么做。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用Vue.nextTick(callback)。这样回调函数在 DOM 更新完成后就会调用。
总结: 以上就是vue的nextTick方法的实现原理了.
- vue用异步队列的方式来控制DOM更新和nextTick回调先后执行
- microtask因为其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕
- 因为兼容性问题,vue不得不做了microtask向macrotask的降级方案