面试必问:React和Vue各自是如何更新视图的?

开发 前端
React 组件的 ​​state​​ 是不可变的,每次更新状态时,我们并不会直接修改原来的 state,而是创建一个新的 state 对象,并用它替换旧的 state。

在 Vue 3 中,响应式系统是基于 Proxy 代理实现的,而 React 的状态管理和更新机制则完全不同。React 并没有使用 Proxy,它主要依赖 状态不可变性(Immutability) 和 调度(Reconciliation) 机制来触发组件更新。

🔍 React 是如何实现状态更新并触发 UI 变化的?

1️⃣  State 是不可变的

React 组件的 state 是不可变的,每次更新状态时,我们并不会直接修改原来的 state,而是创建一个新的 state 对象,并用它替换旧的 state。例如:

const [count, setCount] = useState(0);

const increment = () => {
  setCount(count + 1); // 生成新的 state,触发更新
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

React 通过 setState 或 useState 提供的 setCount 来触发状态更新。因为 count + 1 返回的是一个新的值,所以 React 认为状态已变更。

2️⃣ 触发 Re-render

当 state 发生变化时,React 不会立即更新 UI,而是会:

  1. 触发 调度(Scheduling),将当前组件标记为需要更新;
  2. 合并多个状态更新,在下一次渲染时一起应用;
  3. 重新执行组件函数,得到新的 JSX 结构。

示例:

function Counter() {
  const [count, setCount] = useState(0);

  console.log("组件渲染了"); // 每次 state 更新时,组件都会重新执行

  return (
    <button onClick={() => setCount(count + 1)}>
      Count: {count}
    </button>
  );
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

每次 setCount 触发时,React 不会直接修改 DOM,而是会重新执行 Counter 组件函数,生成新的 JSX,然后 React 通过 Diffing 算法 找出变化的地方,再进行高效的 DOM 更新。

3️⃣ Diffing 和 Reconciliation 机制

当 state 发生变化时,React 并不会暴力重新渲染整个页面,而是:

  • 比较(Diffing)新旧 Virtual DOM,找出变化的部分;
  • 高效更新(Reconciliation) 只修改受影响的 DOM 片段。

示例:

function App() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <h1>Hello</h1>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

在 setCount(count + 1) 触发后:

1.React 重新执行 App 组件,生成新的 Virtual DOM

<div>
  <h1>Hello</h1>
  <p>Count: 1</p>  // 变化的地方
  <button>Increment</button>
</div>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

2.React 发现 h1 和 button 没变,只更新 <p> 标签的文本内容,而不是整个 div

4️⃣ React 为什么不用 Proxy?

Vue 3 通过 Proxy 直接监听对象的变化,实现细粒度的响应式,而 React 依赖 不可变数据 和 Virtual DOM: ✅ React 方案的优势:

  • 避免直接修改对象,防止副作用(确保状态变更可预测)。
  • 优化性能:通过 Diffing 机制减少不必要的 DOM 更新。
  • 适用于函数式编程,配合 useStateuseReducer 等 hook 进行状态管理。

❌ 缺点:

  • 需要手动使用 setState,不像 Vue 那样直接修改对象就会自动触发更新。
  • 深层嵌套对象需要手动更新:
const [user, setUser] = useState({ name: "Alice", age: 25 });

setUser({ ...user, age: 26 }); // 不能直接 user.age = 26
  • 1.
  • 2.
  • 3.
  • Vue 通过 Proxy 代理可以自动检测到 user.age = 26 的变化,而 React 需要创建新对象才能触发更新。

🏆 总结:React 如何更新 UI?

  1. 状态不可变(Immutability):每次修改 state 时,必须创建新的对象或值。
  2. 组件重新执行:当 state 变化时,React 重新运行组件函数,返回新的 JSX 结构。
  3. Diffing & Reconciliation
  • React 比较新旧 Virtual DOM,找出变化的部分;
  • 只更新需要修改的 DOM 节点,而不是整个页面。

👉 这就是 React 不用 Proxy 也能高效更新 UI 的关键!

Vue 3 的更新过程主要依赖 响应式系统(基于 Proxy 和 虚拟 DOM(Virtual DOM),它能够高效地追踪数据变化,并只更新需要修改的部分 DOM。下面详细解析 Vue 3 的更新过程。

🔥 Vue 3 是如何触发 UI 更新的?

1️⃣ 响应式系统(Reactive System)

Vue 3 通过 Proxy 代理对象的 get 和 set 操作,实现自动追踪依赖 & 触发更新。当你修改 state 时,Vue 会:

  • 追踪数据(依赖收集)
  • 检测变化(触发更新)
  • 重新渲染 Virtual DOM 并更新真实 DOM

👀 示例:Vue 3 如何监听数据变化

import { reactive } from "vue";

const state = reactive({ count: 0 });

console.log(state.count); // 访问属性时,Vue 记录依赖
state.count++;  // 修改属性时,Vue 触发更新
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

Vue 3 通过 Proxy 代理 state,监听 count 变化,自动通知视图更新。

Vue 2 使用 Object.defineProperty() 只能监听对象已有的属性,Vue 3 的 Proxy 解决了这个局限,支持监听新增/删除的属性。

2️⃣ 依赖收集(Dependency Collection)

Vue 需要知道哪些组件或计算属性依赖 state.count,这样当 count 变化时,它只会更新受影响的组件,而不是整个应用。

工作流程:

  • 当组件渲染时,Vue 访问 state.count,触发 get,将该组件注册为 count 的依赖(收集副作用 effect)。
  • 以后 count 变化时,Vue 会通知所有依赖它的地方更新。

示例:

import { reactive, effect } from "vue";

const state = reactive({ count: 0 });

// 创建一个副作用(Effect)
effect(() => {
  console.log("Count changed:", state.count);
});

state.count++; // 修改时触发 effect,打印 "Count changed: 1"
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

在 Vue 组件内部,effect() 由 Vue 自动管理,开发者无需手动调用。

3️⃣ 触发更新(Trigger & Scheduler)

当 state.count++ 发生时,Vue 触发 set 操作:

  1. Vue 先检查 count 是否真的变化(新值 !== 旧值)。
  2. 如果变化了,Vue 通知 effect(视图更新逻辑)重新执行。
  3. Vue 使用 调度器(Scheduler) 合并多个状态更新,避免不必要的重复渲染。

示例:多个状态变化会合并更新

<script setup>
import { reactive } from "vue";

const state = reactive({ count: 0 });

function increment() {
  state.count++;  
  state.count++;  // Vue 不会触发两次 DOM 更新,而是合并优化
}
</script>

<template>
  <p>{{ state.count }}</p>
  <button @click="increment">+2</button>
</template>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

Vue 通过 nextTick() 机制合并更新,减少 DOM 操作,提高性能。

4️⃣ 重新渲染 Virtual DOM

当 state.count 变化后:

  1. Vue 重新执行组件的渲染函数,生成新的 Virtual DOM(虚拟 DOM) 结构。
  2. Vue 对比新旧 Virtual DOM(Diffing 算法),找出变化的部分。
  3. Vue 只更新变更的 DOM 节点,而不是整个页面。

5️⃣ Diffing & Patch 过程

Vue 3 使用 Patch Algorithm 进行高效的 DOM 更新:

  • 如果 Virtual DOM 结构没变(只是内容变了),Vue 直接更新文本内容。
  • 如果子元素顺序发生变化,Vue 采用最小修改策略,只移动必要的节点,而不是全部重绘。

示例:

<template>
  <ul>
    <li v-for="item in list" :key="item.id">{{ item.text }}</li>
  </ul>
</template>

<script setup>
import { reactive } from "vue";

const list = reactive([
  { id: 1, text: "Vue" },
  { id: 2, text: "React" }
]);

setTimeout(() => {
  list.reverse(); // Vue 只会调整 DOM 位置,而不会重新创建 <li>
}, 2000);
</script>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

Vue 只移动 <li> 位置,而不会销毁 & 重新创建整个列表。

🎯 Vue 3 的 UI 更新完整流程

1️⃣ 访问响应式数据(Proxy get) → 触发依赖收集

2️⃣ 数据变更(Proxy set) → 触发更新(Effect 重新执行)

3️⃣ Vue 重新执行渲染函数,生成新的 Virtual DOM

4️⃣ Vue 进行 Diffing,找出变更的 DOM 节点

5️⃣ Vue 使用 Patch 机制,仅更新需要修改的部分 DOM

相比 Vue 2,Vue 3 在依赖追踪、调度和 Virtual DOM 更新上更高效!

🚀 Vue 3 和 React 更新机制对比

特性

Vue 3

React

响应式原理

Proxy

 代理数据,自动追踪依赖

useState

 / useReducer,数据不可变

依赖收集

访问数据时自动收集(get

组件渲染时自动关联 state

状态变更

set

 操作触发更新

setState()

 触发更新

组件更新机制

重新运行 渲染函数 生成 VDOM

重新执行 组件函数 生成 VDOM

Diff 算法

只更新变化的部分

只更新变化的部分

批量更新

nextTick()

 自动合并

React 事件中 setState 会合并

👉 Vue 3 的 Proxy 监听数据变更,React 通过 useState 返回新对象。Vue 自动追踪依赖,而 React 需要手动 setState

🔥 总结:Vue 3 是如何更新界面的?

  1. Proxy 监听数据变化,访问数据时自动收集依赖,修改数据时自动触发更新。
  2. 依赖收集(Effect 机制),组件只会在需要更新时重新渲染,而不会整个应用重绘。
  3. 批量更新(Scheduler),合并多个 setState 操作,减少不必要的渲染。
  4. Diffing & Patch 机制,Vue 只更新最小范围的 DOM,而不是整个页面。

🔥 Vue 3 更新机制的核心优势

✅ 更精准的依赖追踪:基于 Proxy,比 Vue 2 更高效,支持监听新增/删除属性✅ 更少的渲染开销:只有真正变化的组件才会重新渲染✅ 更高效的 DOM 更新:使用 Diff 算法 & Patch 机制,只更新必要部分

Vue 3 结合了响应式系统 + Virtual DOM,让 UI 更新更智能、更高效。希望这个解析对你理解 Vue 3 的更新机制有帮助!

责任编辑:武晓燕 来源: 大迁世界
相关推荐

2020-09-21 14:35:20

VuenextTick前端

2021-12-27 08:22:18

Kafka消费模型

2023-02-17 08:02:45

@Autowired@Resource

2023-02-01 07:15:16

2020-07-28 08:59:22

JavahreadLocal面试

2023-06-07 08:08:43

JVM内存模型

2021-12-09 12:22:28

MyBatis流程面试

2021-09-10 18:47:22

Redis淘汰策略

2023-02-03 07:24:49

双亲委派模型

2021-12-06 11:03:57

JVM性能调优

2023-02-15 07:03:41

跨域问题面试安全

2020-11-05 13:12:47

红黑树

2019-03-15 19:41:39

MySQL面试数据库

2024-01-05 14:20:55

MySQL索引优化器

2021-12-13 11:12:41

Spring事务失效

2023-02-06 07:01:51

2023-08-15 15:33:29

线程池线程数

2021-12-16 08:21:31

高并发消息中间件

2020-09-29 15:24:07

面试数据结构Hashmap

2020-02-18 14:25:51

Java线程池拒绝策略
点赞
收藏

51CTO技术栈公众号