深入剖析:Vue 3 与 React 渲染机制和生命周期对比

317 阅读7分钟

前言

今天我们将深入探讨并对比 Vue 3 和 React 18 的渲染机制与生命周期。不多做停留,让我们直接开始吧!

image.png

渲染机制

vue3 渲染机制

Vue 3 的渲染机制主要基于虚拟 DOM(Virtual DOM)和响应式系统。这种机制使得 Vue 能够高效地更新界面。

响应式系统

Vue 3 使用了 Proxy API 来实现响应式数据绑定,能够追踪数据的变化并触发更新。响应式系统主要做了两点:

  1. 依赖收集:当组件渲染时,Vue 会收集该组件所依赖的响应式数据。
  2. 变化通知:数据发生变化时,Vue 会通知所有依赖于该数据的组件重新渲染。

虚拟 DOM

Vue 3 使用虚拟 DOM 来提高渲染性能:

  1. 创建虚拟 DOM:当数据发生变化时,Vue 会先在内存中创建一个新的虚拟 DOM 树。
  2. Diff 算法:Vue 通过 Diff 算法比较新旧虚拟 DOM 树的差异,以找到最小的变更。
  3. 实际 DOM 更新:只将变化的部分应用到实际的 DOM 中,这样可以避免不必要的 DOM 操作,提高性能。

渲染流程

Vue 3 的渲染流程大致如下:

  1. 初始化:在组件创建时,Vue 会将模板编译成渲染函数。
  2. 首次渲染:调用渲染函数生成虚拟 DOM 树,并将其渲染到真实 DOM 中。
  3. 数据变化:当响应式数据发生变化时,Vue 会重新计算虚拟 DOM 树。
  4. Diff 和更新:比较新旧虚拟 DOM,并通过最小化的 DOM 操作更新真实 DOM。

理解渲染机制可以帮助我们做些什么呢?

  1. 性能优化
  • 精细控制渲染:通过了解 Vue 3 的虚拟 DOM 和响应式系统,开发者可以避免不必要的渲染,提升应用性能
  • 使用 v-once 和 v-memo:利用这些指令来缓存不需要频繁更新的部分,减少渲染次数。
  1. 高效的状态管理
  • 部状态和全局状态的管理:了解组件的渲染机制可以帮助开发者合理划分局部状态和全局状态,避免不必要的复杂性。
  • 减少状态传递:通过 Vue 3 的组合式 API,状态可以更加灵活地在组件间传递,从而减少过多的 props 传递。
  1. 提高可维护性:
  • 组件的清晰结构:理解渲染过程可以帮助开发者设计结构更清晰、可重用性更高的组件。
  • 使用组合式 API:Vue 3 引入的组合式 API 使得代码逻辑更易于理解和维护。
  1. 增强用户体验:
  • 响应式更新:通过深入了解响应式系统,开发者可以确保数据变化时 UI 能够及时更新,提升用户体验。
  • 动态组件和异步组件:合理利用动态和异步组件加载,减少初始渲染的负担,提高应用的响应速度。

React18

渲染机制

  1. 组件的初始渲染
  • 当应用程序首次加载时,React 会调用根组件的 render 方法,生成虚拟 DOM 树。
  • React 将此虚拟 DOM 树与实际 DOM 进行对比(初次渲染时为空),并将生成的元素渲染到页面上。
  1. 状态或属性变化
  • 当组件的 state 或 props 发生变化时,React 会重新调用组件的 render 方法,生成新的虚拟 DOM 树。
  1. 虚拟 DOM 树的对比(Diffing)
  • React 使用高效的 diff 算法比较新旧虚拟 DOM 树,识别出需要更新的部分。
  • 只有发生变化的部分会被标记为需要更新,React 会计算出最小的 DOM 更新操作。
  1. 更新真实 DOM
  • React 将变化部分更新到实际 DOM 中,从而实现用户界面的更新。
  1. 函数作为 props 的处理
  • 当将函数作为 props 传递给子组件时,如果父组件重新渲染且不使用 useCallback,则每次都会生成新的函数实例。 这可能导致子组件的重新渲染,即使函数的逻辑未发生变化。使用 useCallback 可以保持函数引用不变,从而避免不必要的子组件渲染。
  1. 子组件的渲染
  • 如果子组件使用了 React.memo 或 shouldComponentUpdate,则子组件会根据其接收到的 props 是否变化来决定是否重新渲染。 如果使用了 useCallback,子组件在接收到相同的函数引用时,将不会重新渲染。

理解渲染机制可以帮助我们做些什么呢?

  1. 性能优化
  • 避免不必要的重新渲染:通过使用 useCallback 和 React.memo,我们可以减少子组件的重新渲染,优化应用的性能。
  • 延迟渲染:通过条件渲染和懒加载,可以减少初始渲染时的 DOM 元素数量,提高页面加载速度。 合理管理状态:
  1. 局部状态管理
  • 理解组件的状态变化可以帮助我们合理地将状态分配到合适的组件中,避免全局状态管理导致的复杂性
  • 减少状态提升:可以将状态放在需要它的组件中,而不是提升到父组件,从而减少渲染次数。

生命周期

渲染机制与生命周期密切相关,接下来,让我们继续深入探讨和对比 Vue 3 与 React 18 的生命周期。

Vue3

image.png

  1. 创建阶段(Initialization):
  • beforeCreate: 在实例初始化之后、数据观察 (data observation) 和事件/侦听器配置之前被调用。
  • created: 在实例创建完成后被立即调用。在这一步,实例已完成数据观察、属性和方法的运算、侦听器的设置等。
  1. 挂载阶段(Mounting):
  • beforeMount: 在挂载开始之前被调用:相关的 render 函数首次被调用。
  • mounted: 挂载到实例上去之后调用。在这一步,组件 DOM 已经被新建。
  1. 更新阶段(Updating):
  • beforeUpdate: 数据更新时调用,发生在虚拟 DOM 打补丁之前。
  • updated: 组件的数据变化导致的虚拟 DOM 重新渲染和打补丁后调用。
  1. 卸载阶段(Unmounting):
  • beforeUnmount: 卸载组件实例之前调用。
  • unmounted: 卸载组件实例之后调用。

React18

image.png

  1. 挂载阶段(Mounting):
  • constructor: 组件的构造函数,最先被执行,常用于初始化状态。
  • static getDerivedStateFromProps: 在调用 render 方法之前调用,并在每次渲染之前调用。
  • render: 组件渲染的核心方法。
  • componentDidMount: 组件挂载到 DOM 后调用,常用于请求数据。
  1. 更新阶段(Updating):
  • static getDerivedStateFromProps: 参数更新时调用。
  • shouldComponentUpdate: 返回 false 可以避免更新。
  • render: 更新时被调用。
  • getSnapshotBeforeUpdate: 在最新的渲染输出提交到 DOM 之前运行。
  • componentDidUpdate: 更新后调用。
  1. 卸载阶段(Unmounting):
  • componentWillUnmount: 组件卸载及销毁之前直接调用。

对比

  1. 通用性与灵活性Vue 的生命周期方法更加细分,如分别有初始化前后的钩子,而 React 则侧重于渲染流程控制
  2. 更新控制React 的 shouldComponentUpdate 和 getSnapshotBeforeUpdate 提供了更细致的控制更新的能力
  3. 响应式系统与状态管理Vue 的生命周期更依赖于其响应式系统,而 React 则依赖于状态和属性的管理

总结

我们已经从 Vue 3 和 React 的渲染机制对比,到它们的生命周期方法进行了讨论,这些理解将帮助我们更有效地控制和优化 Vue 和 React 程序。如果有任何误解或需要更多解释的地方,请在评论区留言,感谢大家的关注和支持。