Post on: Dec 9, 2025Last edited: Dec 10, 2025Words 2567Read Time 7 min

type
status
date
slug
summary
tags
category
icon
password

Vue 的响应式系统

Vue 的响应式系统是其核心功能之一,它使得数据的变化能够自动同步到 DOM 中,从而实现双向数据绑定。Vue 3 使用了 Proxy 对象来实现数据的响应式,而 Vue 2 使用的是 Object.defineProperty 来实现。

让我们从 Vue 3 的实现开始

1. Proxy 对象

Vue 3 使用 Proxy 对象来实现数据的响应式。Proxy 对象可以在数据访问和修改的时候监听进行拦截操作。具体来说,Vue 3 在创建一个 Vue 实例时,会使用 Proxy 来包裹所有实例数据。

2. 依赖收集

当数据发生变化时,Vue 会收集依赖,并且在数据变动时通知所有依赖它的变量去更新。

依赖收集过程

  1. 读取数据时收集依赖:当模板中使用了双花括号表达式(即 v-model="message"{{ message }})时,Vue 会在 get 方法中收集这些依赖。
  1. 数据变更时通知依赖:当数据被修改时(通过 set 方法),所有依赖这个数据的变量都会在下次渲染时被通知,从而重新计算和渲染。

3. 发布-订阅模式

Vue 使用发布-订阅模式来管理依赖关系。它在 getset 方法中传递依赖信息,当数据变更时,通过发布通知所有依赖的视图进行更新。

示例代码

下面是一个使用 Vue 3 的响应式示例:

Vue 2 的实现

在 Vue 2 中,响应式系统是通过 Object.defineProperty 实现的。Vue 2 在数据对象上覆盖了属性的 getset 方法:

依赖收集举例

总结

Vue 的响应式系统的核心是通过 ProxyObject.defineProperty 来拦截数据的读取和修改操作,并在数据变化时通知所有依赖它的视图进行更新。依赖收集和发布机制确保了数据变化时视图的自动更新。

生命周期钩子的基本概念

以下是一些常见的生命周期钩子及其执行顺序:
  • beforeCreate:实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
  • created:实例创建完成后被调用,这时的实例已经完成了数据观测 (data observer) 和 event/watcher 事件配置。
  • beforeMount:在挂载开始之前被调用,并且在虚拟 DOM 树生成之后,DOM 树生成之前。
  • mounted:在挂载完成后被调用,DOM 已经渲染完成了。
  • beforeUpdate:组件更新时,数据变动之前调用。
  • updated:在渲染完成后调用 (三个钩子:beforeUpdateupdated 仅在 keep-alive 组件中首次激活和重新激活时调用)。
  • beforeDestroy:实例销毁之前调用。
  • destroyed:实例销毁后调用。
  • activated:当 keep-alive 中的组件激活时调用。
  • deactivated:当 keep-alive 中的组件停用时调用。

示例场景

假设你正在开发一个简单的计数器应用,用户可以点击按钮增加计数,并且想要记录每次计数的变化情况。你可以使用 beforeUpdateupdated 生命周期钩子来记录这些信息。

解释

  1. beforeUpdate
      • beforeUpdate 钩子中,组件即将进行更新,但是更新之前的 DOM 还没变化。这里可以记录更新前的 count 值。
      • 上述代码中的 beforeUpdate 钩子会在每次数据变化并更新 DOM 前打印即将更新的 count 值。
  1. updated
      • updated 钩子在组件更新并完成之后执行。这里可以记录更新后的 count 值。
      • 代码中的 updated 钩子会在每次数据变化并更新 DOM 后打印更新后的 count 值。

更复杂的场景

假设你需要在组件激活和停用时记录某些状态,可以使用 activateddeactivated 钩子。

解释

  1. activated
      • activated 钩子在组件被激活(从挂载到视图中的 keep-alive 组件重新显示)时调用。你可以在这个钩子中初始化一些状态或进行必要的操作。
      • 代码中的 activated 钩子会在组件重新激活时打印当前的 count 值。
  1. deactivated
      • deactivated 钩子在组件被停用(从挂载到视图中的 keep-alive 组件移除)时调用。你可以在这个钩子中清理一些状态或资源。
      • 代码中的 deactivated 钩子会在组件停用时打印当前的 count 值。

总结

通过使用这些生命周期钩子,你可以在组件的不同阶段执行自定义逻辑,帮助你更好地控制组件的行为和状态。

Vue 基本工作原理

Vue 是一个渐进式框架,它的核心是高效的双向数据绑定。Vue 的关键组件包括:
  • 虚拟 DOM:Vue 使用虚拟 DOM 来提高渲染性能。
  • 数据绑定:Vue 实现了双向数据绑定,当数据发生变化时,UI 会自动更新;反之亦然。
  • 生命周期钩子:Vue 组件在不同阶段会触发特定的生命周期钩子,开发者可以在这个阶段插入自定义的逻辑。

虚拟 DOM

  1. 创建虚拟 DOM:Vue 将真实的 DOM 节点转换为虚拟节点(VNode),这样可以减少直接操作真实 DOM 节点的需求。
  1. 对比 VDOM 和 RDOM:Vue 每次渲染时都会对比当前的虚拟 DOM 和上一次的虚拟 DOM,计算最小的差异,然后通过最小差异来更新真实的 DOM。这样可以极大地减少对真实 DOM 的操作。

双向数据绑定

  1. 响应式系统:Vue 使用了依赖收集和发布模式来实现数据的实时更新。当数据发生变化时,所有依赖于该数据的视图都会自动更新。
  1. 计算属性和侦听器:开发者可以使用 computedwatch 来实现复杂的响应式逻辑。

生命周期钩子

  1. 创建阶段beforeCreatecreatedbeforeMountmounted
  1. 更新阶段beforeUpdateupdated
  1. 销毁阶段beforeDestroydestroyed

渲染过程

  1. 预编译:把模板编译成一个 render 函数。
  1. 静态编译:优化生成的 render 函数,处理静态内容。
  1. 动态编译:保留动态内容,确保它们能够响应数据变化。

示例代码

你可以通过以下代码示例来了解 Vue 是如何创建 render 函数的:
这段代码会生成一个 render 函数,其中包含对 message 数据的绑定以及按钮的事件处理。你能在 Vue 的文档中找到更多关于 render 函数的详细介绍。
 

Vue 的编译过程

预编译

当你使用模板写法时,Vue 会使用一个专用的 compiler 生成一个 render 函数。这个 render 函数是一个 JavaScript 函数,它直接操作虚拟 DOM(VDOM)。模板会被编译成一个 render 函数,这个函数会被注入到 Vue 组件中,并在组件实例化后执行。

静态编译

render 函数生成后,Vue 会对其进行优化,处理静态内容。静态内容通常不会随数据变化而变化,所以 Vue 会将这些静态节点转为最精简的 HTML。这样在渲染过程中可以大大减少 DOM 操作的次数,从而提高性能。

动态编译

对于动态内容,比如根据数据变化的内容,Vue 会保留这部分节点,确保它们能够响应数据变化。这些动态节点在 render 函数中会用到实际的数据属性和方法。
关于编译过程,重点在于 Vue 如何区分静态内容和动态内容,并如何生成对应的 render 函数。你能试着描述一下这些概念吗?或者你有什么疑问的地方我可以详细解释。

Loading...
每日学习记录

🗒️每日学习记录

计算机基础

🗒️计算机基础