⚡ 30 秒速记

  • 核心判断:理解原理要建立输入、状态变化、输出和失败边界,而不是只记 API 与结论
  • 原理主线:围绕 「Vue 异步更新 DOM 原理」、「总结」、「核心机制」 建立输入、状态变化与输出之间的因果关系
  • 文章范围:解析了Vue中数据变更到视图异步更新的完整流程,介绍了Data、Dep、Watcher等核心对象的作用,阐释了为什么Vue更新DOM是异步的,以及如何通过$nextTick获取最新的DOM状态,帮助读者深入理解Vue异步渲染机制。
  • 边界与代价:文章中的实现通常有版本和场景前提,迁移到当前项目时必须先核对运行环境与依赖
  • 工程落地:面试回答按核心机制、执行链路、边界反例和工程验证展开,最后说明取舍

Vue 更新数据后不会立即操作 DOM,而是把相关 Watcher 去重后放进队列,在下一个 tick 统一刷新。 队列会按 Watcherid 排序,使父组件优先更新,并处理刷新期间新增的任务。nextTick 会优先借助 Promise 等异步机制执行回调,所以在 $nextTick 中通常能读到更新后的 DOM。这里描述的是 Vue 2 的调度链路,Vue 3 的实现角色已经换成 Proxyeffect 和新的渲染器。

这篇文章不要按 API 清单来背。先用上面的 Mind Map 建立全局结构,再通过交互 DEMO 观察正常路径和边界路径如何改变状态;阅读正文时重点核对每一步的输入、负责执行的参与者、产生的中间状态以及最终可观察结果。遇到版本敏感结论,要把“历史实现”“当前行为”和“工程兼容策略”分开说明;遇到性能或架构取舍,则用实际指标、失败现象和验证手段支撑判断。

版本校准: 本文出现 Object.definePropertyDepWatcher 和双端 Diff 时,主要描述 Vue 2 实现;Vue 3 使用 Proxyeffect 与新的渲染器路径。Vue 2 已于 2023-12-31 结束维护,新项目应以 Vue 3 为基线,旧项目参考 Vue 2 EOL 官方说明 制定迁移与安全策略。

本文主要分析 Vue 从 Data 更新,到通知 Watcher 异步更新视图的流程,也就是下图中的橙色部分。

我们先来回顾一下图中的几个对象:

  • Data 对象:Vue 中的 data 方法中返回的对象。
  • Dep 对象:每一个 Data 属性都会创建一个 Dep,用来搜集所有使用到这个 Data 的 Watcher 对象。
  • Watcher 对象:主要用于渲染 DOM。

接下来,我们就开始分析这个流程。

# Vue 异步更新 DOM 原理

很多同学都知道,Vue 中的数据更新是异步的,意味着我们在修改完 Data 之后,并不能立刻获取修改后的 DOM 元素。

<template>
  <div>
    <span id="text">{{ message }}</span>
    <button @click="changeData">
      changeData
    </button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: "hello",
    };
  },
  methods: {
    changeData() {
      this.message = "hello world";
      const textContent = document.getElementById("text").textContent;
      // 直接获取,不是最新的
      console.log(textContent === "hello world"); // false
            // $nextTick 回调中,是最新的
      this.$nextTick(() => {
        const textContent = document.getElementById("text").textContent;
        console.warn(textContent === "hello world"); // true
      });
    },
  },
};
</script>
webapp
公众号
开发者导航
切换夜间模式
点击侧边栏上一篇
点击侧边栏下一篇
折叠侧边栏
收起全部