手写nextTick,带你了解nextTick

695 阅读3分钟

nextTick是什么?

手写nextTick,带你了解nextTick,首先我们先了解一下什么是nextTick,它是做什么用的

nextTick 是一个用于处理异步 DOM 更新的工具,确保在数据变化后 DOM 完成更新时再执行某些操作。由于 Vue 的数据绑定是异步的,nextTick 可以帮助你在数据变化后立即获取更新后的 DOM 状态

可能直接说概念也不好理解,我们直接上案例

这段代码很简单,就是一个span标签和一个按钮修改span里面的内容

JavaScript效果分别是

  • 在挂载之后打印span的值与宽度
  • 修改值后打印span的值与宽度
  • 修改值后再nextTick中打印span的值与宽度
<template>
  <div>
    <span ref="span">{{ message }}</span>
    <button @click="updateMessage">修改</button>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick } from "vue";
const message = ref("Hello Vue!");
const span = ref(null);

// 获取span的宽度
onMounted(() => {
  console.log(span.value);
  console.log(span.value.offsetWidth);
});

// 修改message的值
const updateMessage = () => {
  message.value = "Hello World!";
  // 修改数据后立即获取span的值与宽度
  console.log("立即获取");
  console.log(span.value);
  console.log(span.value.offsetWidth);
  nextTick(() => {
    // 在nextTick中获取span的值与宽度
    console.log("nextTick中获取");
    console.log(span.value);
    console.log(span.value.offsetWidth);
  });
};
</script>

可以看到结果为

image.png

在初始的时候宽度为68,立即修改值之后,从结果可以看到值已经变更了,但是宽度还是原来的68

我们在nextTick中答应出来的才是真实的宽度83

手写nextTick方法

通过打印官方的nextTick,我们可以看到返回值是一个promise

image.png

所以我们自己的nextTick也就是返回一个promise

在手写之前我们先了解一下什么是MutationObserver

MutationObserver

MutationObserver 是一个用于监视 DOM 变更的 JavaScript API。它提供了一种高效的方式来观察 DOM 树的变化,比如添加、删除或修改节点,而不需要依赖于较为繁重的轮询机制。

  • 主要特点
  1. 高效性:与旧的 Mutation Events 不同,MutationObserver 在批量处理变更时效率更高,因为它可以在所有变更完成后一次性通知你。
  2. 异步回调:当观察到变化时,MutationObserver 会在下一个事件循环中调用回调函数,这样可以避免阻塞主线程。
function nextTick(fn) {
  return new Promise((resolve, reject) => {
    // 判断dom 是否已经渲染完毕
    // 判断浏览器是否支持MutationObserver
    if (typeof MutationObserver !== "undefined") {
      const observer = new MutationObserver(() => {
        const res = fn();
        if (res instanceof Promise) {
          res.then((res) => {
            observer.disconnect();
            resolve(res);
          });
        } else {
          observer.disconnect();
          resolve(res);
        }
      });
      observer.observe(document.getElementById("app"), {
        attributes: true,
        childList: true,
        subtree: true,
      });
    }
  });
}
  1. Promise 回调:函数返回一个 Promise,允许调用者通过 .then() 来处理结果。这是处理异步操作的好方式。

  2. MutationObserver 的使用

    • 判断浏览器是否支持 MutationObserver
    • 创建一个观察者来监测指定 DOM 元素的变化。
    • 当观察到变化时,执行传入的回调 fn()
  3. 处理 Promise 结果

    • 如果 fn() 返回一个 Promise,则在 Promise 解析后断开观察并解析主 Promise。
    • 否则,直接断开观察并解析主 Promise。
  4. 观察配置:监听目标元素的属性、子节点和子树的变化。

总结

以上就是本文手写nextTick,带你了解nextTick的全部内容啦,希望看到这里的你能够有所收获!!