diff --git a/hzh/REACT/虚拟 DOM 和 真实 DOM 有什么区别.md b/hzh/REACT/虚拟 DOM 和 真实 DOM 有什么区别.md
new file mode 100644
index 0000000..ad9a7ac
--- /dev/null
+++ b/hzh/REACT/虚拟 DOM 和 真实 DOM 有什么区别.md
@@ -0,0 +1,191 @@
+---
+tags: [React, 前端, 虚拟DOM, DOM]
+create time: 2026-05-26 15:30
+---
+
+# 虚拟 DOM 和 真实 DOM 有什么区别
+
+## 概述
+
+虚拟 DOM(Virtual DOM)是 React 的"秘密武器"——它先用 JavaScript 对象在内存中画一张 **UI 蓝图**,然后通过一套高效的 Diff 算法找出改动最少的那部分,最后一次性刷到真实的页面上。这样既省去了频繁操作浏览器 DOM 的性能损耗,又保留了声明式编写 UI 的方便。
+
+## 正文
+
+### 先搞懂:什么是"真实 DOM"?
+
+浏览器加载网页后,会把 HTML 文档转换成一棵节点树,这就是 **DOM 树**。每个 `
`、每段文字都是树上的一个节点。
+
+```html
+
+```
+
+对应的 DOM 树结构:
+
+```mermaid
+graph TD
+ UL["
"] --> LI1["- 苹果
"]
+ UL --> LI2["- 香蕉
"]
+ UL --> LI3["- 橙子
"]
+```
+
+**问题来了**:如果我想在"香蕉"前面加一个"草莓",传统写法是:
+
+```tsx
+// ❌ 传统写法:手动改 DOM
+const list = document.getElementById("list");
+const strawberry = document.createElement("li");
+strawberry.textContent = "草莓";
+list.insertBefore(strawberry, list.children[1]);
+```
+
+看起来简单?但当页面有 100+ 个元素要同时更新时,这种逐条操作的方式会频繁触发浏览器的 **重排(Reflow)** 和 **重绘(Repaint)**,体验明显卡顿。
+
+> [!QUESTION] 为什么多次修改 DOM 这么慢?
+> 想象你在白板上画图:每擦一次就重新描一遍。而批量操作的思路是先画草稿纸,确认没问题了再一次性誊到白板上。
+
+### 虚拟 DOM:DOM 树的"替身演员"
+
+虚拟 DOM 不是新东西——它只是 **用 JS 对象模拟 DOM 树的一份副本**:
+
+```tsx
+// JSX 写法(你写的)
+const element = ;
+
+// React 内部实际生成的虚拟 DOM(纯 JS 对象)
+const vdom = {
+ type: "ul",
+ props: { id: "list", children: [
+ { type: "li", props: { children: ["苹果"] } },
+ { type: "li", props: { children: ["香蕉"] } }
+ ]}
+};
+```
+
+这个对象 **不占用任何浏览器资源**,只在 JS 内存里跑。你可以把它理解为装修的 3D 效果图——你看的是图,但房子还没动。
+
+| | 真实 DOM | 虚拟 DOM |
+|---|---------|---------|
+| 是什么 | 浏览器的 DOM 节点对象 | JS 普通对象 |
+| 在哪运行 | 浏览器引擎(C++) | JS 引擎(V8) |
+| 改动成本 | 高(触发布局计算) | 低(只是对象赋值) |
+| 能跨平台吗 | ❌ 只能浏览器 | ✅ SSR、React Native |
+
+### 核心原理:Diff + Patch
+
+虚拟 DOM 的威力不在"虚拟"本身,而在它的 **对比机制**。流程只有三步:
+
+```mermaid
+flowchart LR
+ A["状态变化"] --> B["生成新的虚拟 DOM"]
+ B --> C["新旧对比(Diff)"]
+ C --> D["只更新变动的部分(Patch)"]
+ style A fill:#e1f5fe
+ style B fill:#fff3e0
+ style C fill:#fce4ec
+ style D fill:#e8f5e9
+```
+
+#### 举个例子:添加一项水果
+
+```tsx
+// 第 1 步:原始列表 —— 用户点了"添加草莓"
+setState({ fruits: ["苹果", "香蕉", "橙子"] })
+// ↓
+// 🍎 🍌 🍊
+
+// 第 2 步:React 生成新的虚拟 DOM
+setState({ fruits: ["苹果", "香蕉", "草莓", "橙子"] })
+// ↓
+// 🍎 🍌 🍓 🍊
+
+// 第 3 步:Diff 发现只有 1 处变化
+// Patch 只需执行 1 次操作:- 草莓
插入到香蕉后面
+```
+
+对比两种方式的差异:
+
+```
+直接操作 DOM:
+ ├── insertBefore() ← 触发重排
+ ├── 可能需要调整后续索引 ← 额外逻辑
+
+React 的 VDOM:
+ ├── 创建新 JS 对象 ← 纯内存操作,极快
+ ├── Diff 比较两棵树 ← 内存中运算,也不影响渲染
+ └── 批量应用变更 ← 浏览器只收到一条指令
+```
+
+> [!TIP] CPU 换 GPU 思维
+> 有人问:"Diff 本身也要算啊,不是多了一步吗?"——对,VDOM 确实多了一次 CPU 计算,但它把 N 次昂贵的 GPU(浏览器渲染管线的重排/重绘)合并成 1 次。**用便宜的算力换取昂贵的渲染,这是现代前端的经典权衡。**
+
+#### Diff 是怎么做到这么快?
+
+暴力对比两棵树的复杂度是 O(n³),不可接受。React 做了两个"偷懒"的设计把它们砍到 O(n):
+
+1. **同层对比**:不同层的节点绝不拿来比,类型一变就直接销毁重建
+2. **key 属性**:列表项靠 key 来辨认身份,避免误判
+
+```
+假设列表从 [A, B, C] 变成 [B, A, C]:
+
+暴力对比:逐个位置看,认为 3 个都变了 ❌
+React Diff:通过 key 识别出 B 和 A 只是换了位置,只需交换 ✅
+```
+
+### key 到底是什么?为什么非得加?
+
+`key` 就是虚拟 DOM 对比时的 **身份证**。
+
+```tsx
+// ✅ 正确:用不变的 ID 当 key
+users.map(user => - {user.name}
)
+
+// ❌ 错误:用 index 当 key
+users.map((user, i) => - {user.name}
)
+```
+
+**为什么不能用 index?** 看这个场景:
+
+```
+初始列表:Alice(0), Bob(1), Carol(2)
+删除 Alice 后:Bob 变成了 [0],Carol 变成了 [1]
+
+用 index 当 key:
+ Diff 看到 index=0 的值从 "Alice" 变成了 "Bob"
+ → 认为整个列表全变了,全部重建 ❌
+
+用 user.id 当 key:
+ Diff 看到 id=1 的 "Bob" 只是位置上移了一位
+ → 只做移动,不重建 ✅
+```
+
+> [!NOTE] 什么时候可以用 index?
+> 列表完全不会增删排序、且项之间没有任何状态交互——几乎不存在这样的场景。安全起见,永远用稳定唯一 ID。
+
+### 完整工作流程
+
+```mermaid
+sequenceDiagram
+ participant U as 用户
+ participant R as React
+ participant V as 旧虚拟 DOM
+ participant New as 新虚拟 DOM
+ participant P as Diff 引擎
+ participant D as 真实 DOM
+
+ U->>R: 点击按钮 / setState
+ R->>New: 用最新数据生成新虚拟 DOM
+ R->>P: 传入旧虚拟 DOM 和新虚拟 DOM
+ P->>P: 逐层对比,记录最小变更集
+ P-->>R: 返回需要更新的位置
+ R->>D: 批量写入变更
+ D-->>U: 页面刷新
+```
+
+## 关联笔记
+- [[REACT/React 的生命周期和 Hooks]]
+- [[REACT/React 性能优化策略]]