神奇的nextTick一定能获取到最新的dom么?


theme: awesome-green
highlight: vs2015

前言

众所周知,vuedom更新操作时异步的,为了获取更新后的dom官方提供了相应的apinextTick,文档中对该api的描述为:将回调延迟到下次 DOM 更新循环之后执行 , 所谓的下一次,到底是哪一次呢?dom更新是异步任务,nextTick的回调也是异步任务,nextTick的回调中一定就能获取到最新的dom么?

nextTick的实现原理

vue2x中

出于兼容性考虑,依次判断浏览器是否支持,选择使用对应api

image.png

优先选择微任务,如果微任务都不支持,则选择宏任务

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

  • 图解

nextTick.png

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
相关推荐
  • 暂无相关文章
  • 评论 抢沙发
    头像
    欢迎您留下宝贵的见解!
    提交
    头像

    昵称

    取消
    昵称表情代码图片

      暂无评论内容