nextTick 原理

294 阅读2分钟

做一个总结和学习跟大家分享,希望对大家也有所帮助,共同成长进步💪~
如果大家喜欢,可以点赞或留言哈💕~~~~,谢谢大家⭐️⭐️⭐️~~~

关键点:

确保我们操作的是更新后的 DOM; 这样做可以避免频繁的 DOM 操作,提高性能

背景:

在 Vue 中,DOM 更新是异步执行的,这意味着当我们修改了数据后,DOM 并不会立即更新,而是将 DOM 更新操作放到一个异步队列中,等到下一次事件循环时再执行。这样做可以避免频繁的 DOM 操作,提高性能。

问题:

但是,由于 Vue 的异步更新机制,当我们修改数据后,如果想要立即获取更新后的 DOM,这时是获取不到最新的。这时就需要使用 Vue.nextTick() 方法

原理:

Vue.nextTick() 方法的实现原理是基于浏览器的异步任务队列,采用微任务优先的方式。

当我们修改数据时,Vue 会将 DOM 更新操作放到一个异步任务队列中,等待下一次事件循环时执行。而 Vue.nextTick() 方法则是将一个回调函数推入到异步任务队列中,等待 DOM 更新完成后执行。这样就可以确保我们操作的是更新后的 DOM,而不是更新前的 DOM。

具体实现方式有以下几种:

  1. 在 Vue2.x 中,如果浏览器支持 Promise,则会优先使用;
  2. 如果不支持 Promise,则会使用原生的 setTimeout 方法模拟异步操作;
  3. 如果浏览器支持 MutationObserver,Vue 会使用 MutationObserver 监听 DOM 更新,并在 DOM 更新完成后执行回调函数。
  4. 使用 setlmmediate: 在 lE 中,setlmmediate 方法可以用来延迟异步执行任务。在 Vue2.x 中,如果浏览器支持 setlmmediate,则会优先使用 setlmmediate,否则会使用 setTimeout。

总结:

因为 Vue中视图更新是异步的,而使用 Vue.nextTick() 方法可以保证我们定义的逻辑在DOM更新之后执行,也就是确保我们操作的是更新后的DOM。

它的实现原理是利用浏览器的异步任务队列,它会将用户定义的回调函数推入到异步队列中,在 DOM 更新完成后执行。Vue底层会根据浏览器的支持情况选择合适的异步任务方法。

源码中定义了一个异步逻辑函数timeFunc(),采用优雅降级的方式:

  • 先判断浏览器是否支持 Promise,如果支持则优先使用 Promise.then() 方法来触发执行回调函数;
  • 否则,判断是否支持 MutationObserver,支持的话就会实例化一个观察者对象,观察文本节点发生变化时,执行回调函数;
  • 如果都不支持,则看下当前是否是 IE, 如果是就会采用 setlmmediate 来延迟异步执行任务;
  • 如果再不支持,会利用 setTimeout 设置延时为0。