vue3-DOM树

DOM 树是浏览器理解并呈现网页的"骨架" 。无论你用的是 Vue、React 还是原生 JS,所有前端框架最终都在操作这棵树

结合你的学习进度(Vue3 虚拟 DOM、构建工具),我带你彻底搞懂这棵"树"的物理结构生成过程 ,以及Vue 为什么要搞一个"虚拟 DOM"来模拟它


1. 什么是 DOM 树?(纸上建筑模型)

当浏览器(如 Chrome)加载你的 index.html 时,它做的第一件事不是画图,而是**"读代码,搭积木"**。

定义 :DOM(文档对象模型,Document Object Model)树是一个内存中的多叉树结构 ,它用节点(Node) 的形式完整地表达了 HTML 文档的层级关系。

类比 :想象一栋房子的建筑结构图

  • 根节点(document:就是这块地皮。
  • <html>:房屋的主体框架。
  • <head><body>:房子的水电管道和居住空间。
  • <div><p><button>:房间里的墙壁、家具和开关。

代码映射

复制代码
<!DOCTYPE html>
<html>
  <head>
    <title>我的页面</title>
  </head>
  <body>
    <div id="app">
      <h1>标题</h1>
      <p>段落</p>
    </div>
  </body>
</html>

对应的 DOM 树逻辑结构:

复制代码
document
 └── html
      ├── head
      │    └── title
      │         └── "我的页面"
      └── body
           └── div#app
                ├── h1
                │    └── "标题"
                └── p
                     └── "段落"

2. 这棵树由哪些"积木"(节点)组成?

DOM 树由 不同类型的节点(Node) 构成,你在 Vue 模板中写的标签,最终都会变成以下 3 种主要节点:

节点类型 例子 描述
元素节点(Element) <div>, <p>, <button> 构成网页结构的骨架,可以嵌套子节点
文本节点(Text) "标题", "段落" 叶子节点,没有子级,存放真正的文字内容。
属性节点(Attribute) id="app", class="box" 挂在元素节点上,不属于树的主干(通常不单独算作树的层级)。

3. 浏览器是如何"造"出这棵树的?(关键流程)

当你输入网址并回车,浏览器的渲染引擎(如 Chrome 的 Blink)会经历:

  1. 词法分析(Tokens):将 HTML 字符串拆解成开始标签、结束标签、属性、文本。
  2. 构建节点(Nodes):根据标签创建对应的 JS 对象。
  3. 建立父子关系 :遇到 <div> 就作为当前父节点的最后一个儿子插入,形成 深度优先(DFS) 的树结构。
  4. 触发关键渲染路径 :DOM 树构建完成后,会与 CSSOM 树(样式树) 合并成 Render Tree(渲染树),最终绘制成屏幕上的像素。

4. 致命的痛点:为什么直接操作 DOM 树很"昂贵"?

在原生 JS 中,你写 document.getElementById('app').innerHTML = 'xxx',就是直接修改这棵树。

痛点

  • 回流(Reflow) :当你改了 widthdisplay,浏览器不仅要改这棵树,还要重新计算所有子元素的几何位置(就像你抽走了积木底层的方块,整座塔都要垮塌重建)。
  • 重绘(Repaint) :即使只改了 color 这种不改变布局的属性,浏览器也得重新把像素画一遍。

结论:每秒操作 60 次 DOM 树,很容易造成页面卡顿(掉帧)。


5. Vue 3 的救命稻草:虚拟 DOM(Virtual DOM)与 Diff 算法

既然操作真树这么贵,Vue 就在 JS 内存里造了一棵**"假树(虚拟 DOM)"**。

运作流程

  1. 造梦 :你写了 <template>,Vue 编译成 render 函数,生成一个轻量的 JS 对象(虚拟 DOM 树)
  2. 挂载:Vue 拿着这棵虚拟树,一次性创建真实的 DOM 树。
  3. 变化 :数据变了(比如 message.value 变了),Vue 生成新的虚拟树
  4. 对比(Diff) :Vue 拿出 "新树""老树" 对比,找出具体是哪个节点、哪个属性变了(这个算法叫 Patch)。
  5. 打补丁 :Vue 只去修改那一个真实的 DOM 节点,其他几百个没变的节点原封不动

这就是你之前学的 v-for 必须加 :key 的底层原理:key 是给虚拟 DOM 树上的节点打上的"身份证号",让 Diff 算法能精确判断是"移动了位置"还是"完全新建",从而极大提升 DOM 树的复用效率!


6. 结合你的代码看,DOM 树在哪里?

在你的 Vue 父组件中:

复制代码
<template>
  <div class="parent-component">   <!-- 1. 真实 DOM 树的起点 -->
    <h3>👨‍👦 父组件</h3>           <!-- 2. 文本节点 -->
    <ChildComponent />             <!-- 3. 这是 Vue 的"组件节点",在 DOM 树上会被替换为组件内部的真实元素 -->
  </div>
</template>
  • 最终在浏览器控制台(F12 -> Elements)中看到的,全是真实的 DOM 树节点
  • 而你的 ChildComponent 在编译阶段,会被 Vue 打平或插入,最终成为真实 DOM 树上的一个 <div> 子树。

7. Windows 11 开发者工具中的上帝视角

想亲眼看这棵树长什么样?在 Chrome/Edge 中:

  1. F12 打开开发者工具。
  2. 点击 Elements(元素) 标签。
  3. 你看到的那个可折叠、缩进的层级结构 ,就是当前页面在内存中的 真实 DOM 树
  4. 如果你开了 Vue Devtools,你看到的是一棵虚拟组件树,它更清晰,但不完全等于 DOM 树。

总结一句话记忆

DOM 树是浏览器内存中一颗由 HTML 标签构成的"家族谱系树",操作它非常消耗性能;而 Vue 在 JS 里造了一颗"模拟树(虚拟 DOM)",通过 Diff 算法精准只修改真实树上的必要部分,这就是 Vue 性能优化的核心密码。

现在打开你正在运行的项目,按 F12 看 Elements,再打开 Vue Devtools 看组件树,对比一下两者的映射关系------以后碰到性能问题,你脑海里就会浮现这两棵树的对比图!😄

相关推荐
谷哥的小弟1 小时前
TypeScript中的any
javascript·typescript
白狐_7982 小时前
408数据结构:中缀转后缀与操作符栈容量——真题精讲
前端·javascript·数据结构
谷哥的小弟2 小时前
TypeScript在Vue3中的常见写法
前端·javascript·typescript
人间凡尔赛2 小时前
2026 前端全栈新范式:Server Actions + Edge Runtime,告别传统 API 路由
前端·全栈·next.js
mONESY3 小时前
用 useRef 管理 Worker 线程,让你的页面不再卡顿
javascript
码林鼠5 小时前
2026前端面试题(二)
前端
满栀5856 小时前
请求拦截、响应拦截、业务错误统一处理
前端·typescript·anti-design-vue
vx-程序开发7 小时前
django医院预约挂号系统---附源码23353
java·javascript·spring boot·python·eclipse·django·php
宿6747 小时前
tsconfig.node.json
前端·javascript·vue.js