06 / 09

Hydration 为什么不是重新渲染?

区分 SSR、客户端渲染与 Hydration,理解 Vue 如何接管现有 HTML。

Hydration 为什么不是重新渲染?

学习目标

理解 Hydration 的真正含义,并区分 SSR、Hydration、浏览器渲染、onMounted()。

学完本章,你应该能够回答:

  • Hydration 到底在做什么?
  • 为什么它不是重新渲染?
  • onMounted 为什么不会导致 SSR 报错?

一、这个知识解决什么问题?

上一章我们已经知道:浏览器第一次拿到的是服务器生成的 HTML。

那么问题来了,浏览器下载完 Vue 以后,它会不会重新执行一遍组件、重新生成一遍 HTML?

如果重新生成,服务器提前渲染还有什么意义?

Vue 下载完成以后,到底做了什么?


二、一起推导

服务器已经生成了 HTML,浏览器已经显示出来。现在 Vue 下载完成,有两种选择:

方案一:全部删除,重新创建

可以,但会导致页面闪烁、浪费性能、SSR 等于白做。Vue 不会这样设计。

方案二:直接接管已有 HTML

既然 <button>Click</button> 已经显示,Vue 不需要重新创建它,只需要:

  • 绑定 @click
  • 绑定响应式
  • 绑定生命周期

于是这个静态 HTML 瞬间变成 Vue 应用。这就是 Hydration


三、Hydration 的真正含义

Hydration 并不是"重新渲染",真正发生的是:

服务器 → 生成 HTML → 浏览器显示 → Vue 下载完成
                                   绑定事件 + 响应式
                                   应用开始运行

整个过程 HTML 几乎没有变化,变化的是:

HTML 被 Vue 接管了。

所以 Hydration 更准确的理解是:接管(Attach),而不是重新创建(Re-render)


四、脑图

Nuxt Hydration 脑图:复用 SSR DOM 并绑定事件与响应式

读图时要区分"执行组件"和"创建真实 DOM":

  1. 客户端仍然需要执行组件逻辑,建立响应式状态并生成虚拟 DOM
  2. Vue 会用虚拟 DOM 去遍历、核对服务器留下的真实 DOM
  3. 两者一致时,Vue 复用原有节点,关联响应式更新并绑定事件监听
  4. 当前组件完成 Hydration 后,才进入 mounted 阶段

Hydration 复用的是 DOM,补上的是客户端运行能力

客户端第一次计算出的结构应该和服务器 HTML 一致,否则就会进入下一章的 Hydration Mismatch。


五、为什么叫 Hydration?

Hydration 原意是给东西注入水分

可以把 SSR 理解成一尊雕像——已经做好,但没有生命。Hydration 就像给雕像注入生命。雕像没有重新雕刻,只是活了


六、onMounted 为什么不会报错?

onMounted(() => {
    console.log(window.innerWidth)
})

为什么不会 SSR 报错?原因就在执行顺序:

SSR → HTML 返回浏览器 → Hydration → onMounted()

onMounted 是 Hydration 完成以后才执行的,此时代码已经运行在浏览器,浏览器拥有 window,所以不会报错。


七、容易踩坑

❌ Hydration = 重新渲染

不是。真正发生的是接管已有 HTML。

❌ Vue 下载完成以后重新生成页面

不是。Vue 直接复用服务器返回的 HTML。

❌ onMounted 在 SSR 阶段执行

不是。它发生在 SSR → Hydration → Mounted 之后,因此可以安全访问 windowdocumentlocalStorage


一句话记忆

SSR 负责画页面,Hydration 负责让页面"活起来"。