nextTick能否获取到最新dom原理解析
远山无期 人气:0前言
众所周知,vue
的dom
更新操作时异步的,为了获取更新后的dom
官方提供了相应的apinextTick
,文档中对该api的描述为:将回调延迟到下次 DOM 更新循环之后执行 , 所谓的下一次,到底是哪一次呢?dom
更新是异步任务,nextTick
的回调也是异步任务,nextTick
的回调中一定就能获取到最新的dom么?
nextTick的实现原理
vue2x中
出于兼容性考虑,依次判断浏览器是否支持,选择使用对应api
优先选择微任务,如果微任务都不支持,则选择宏任务
vue3中:
抛弃了兼容性,直接使用Promise,来实现nextTick
结论
由nextTick
的源码可以看出,nextTick
本质就是创建了一个微任务(不考虑setTimeout
),将其回调推入微任务队列。vue
中一个事件循环中的所有dom
更新操作也是一个微任务,两者属于同一优先级,执行先后只于入队的先后有关,换句话说,如果你先写了nextTick
,再写赋值语句(在此之前没有触发dom更新的操作),那在nextTick中获取的可就不是更新后的dom
了
示例说明
- 例如下面的代码:
<template> <div class="demo"> <p class="name">{{ name }}</p> <button @click="modify">修改</button> </div> </template> <script lang="ts" setup> const name = ref("111"); const modify = () => { name.value = "222"; // 关键的赋值语句,如果注释掉,结果就大不一样了 nextTick(() => { const text = document.querySelector<HTMLElement>(".name").innerText; console.log(text); }); name.value = "333"; }; </script>
如上代码,如果注释掉name.value = "2222"
,虽然nextTick语句下面也有赋值操作:name.value = "3333";
,但由于nextTick先进入微任务队列,所以回调先于dom更新执行,所以是获取的dom仍旧是旧的更新前的dom
- 图解
加载全部内容