第 7 卷
- 用Proxy替代Object.defineProperty,解决Vue2响应式的固有缺陷(如无法监听对象新增/删除属
性、数组索引修改等);
- 支持Map、Set等ES6集合类型的响应式,响应式覆盖范围更广。
- 新增组合式API(Composition API):
- 替代传统选项式API(Options API)的逻辑组织方式,通过 setup 函数、 ref、
reactive、 computed 等API,实现逻辑的抽离与复用;
- 解决Options API中“逻辑碎片化”问题,便于维护大型组件的复杂逻辑。
- 编译优化:
- 引入PatchFlags(补丁标记):编译阶段标记动态节点(如动态文本、动态class),运行时只更
新标记节点,减少虚拟DOM对比开销;
- 静态提升:将静态节点(如固定文本、无动态绑定的元素)提升到渲染函数外部,避免每次渲染
重新创建,提升性能;
- 支持Tree-shaking:编译时移除未使用的代码,进一步减小打包体积。
- 性能大幅提升:
- 虚拟DOM重写:优化diff算法,减少节点对比次数;
- 减少重渲染:通过响应式系统的精准依赖收集,只触发依赖状态变化的组件重渲染;
- 初始化速度提升:相比Vue2,初始化时间减少约55%,内存占用减少约50%。
- 更好的TypeScript支持:
- Vue3源码采用TypeScript编写,原生支持类型推导,无需额外编写大量类型声明;
- 组合式API与TS结合更自然,可精准约束状态和函数类型,提升代码健壮性。
- 其他API与特性改进:
- 生命周期钩子调整:新增 onRenderTracked、 onRenderTriggered 等钩子,便于调试响
应式依赖;
- 模板语法增强:支持多根节点组件、Teleport(传送门)、Suspense(异步组件加载)等新特
性;
- 自定义指令API优化:简化指令的生命周期钩子(如 bind → beforeMount、
update → updated),更贴近组件生命周期。
19. Vue3的响应式系统工作原理 & 与Vue2的实现差异
- 创建响应式对象:
2.reactive:用于对象/数组类型,通过 new Proxy(target, handler) 创建目标对象的代理,拦截对象的属性访问( get)、修改( set)、删除( deleteProperty)等操作;
3.ref:用于原始类型(string、number等),通过封装一个包含 value 属性的对象,再对 value 属性使用Proxy实现响应式,外部通过 ref.value 访问和修改。
- 依赖收集(track):
- 当副作用函数(如组件渲染函数、watch回调)执行时,访问响应式对象的属性,触发Proxy的
get 拦截器;
6.get 拦截器调用 track 函数,建立“响应式对象→属性名→副作用函数”的映射关系,存储在全局的 targetMap(WeakMap类型)中,完成依赖收集;
- 映射结构: WeakMap<target, Map<key, Set<effect>>>,确保响应式对象被销毁时,
依赖自动回收,避免内存泄漏。
- 副作用触发(trigger):
- 当修改响应式对象的属性时,触发Proxy的 set(修改/新增)或 deleteProperty(删除)拦
截器;
- 拦截器调用 trigger 函数,从 targetMap 中查找该属性对应的所有副作用函数,将其加入执
行队列;
- 队列去重后,异步执行副作用函数,完成视图更新或其他逻辑。
二、与Vue2响应式实现的核心差异
对比维度Vue2Vue3(Proxy)
(Object.defineProperty)
核心APIObject.defineProperty,拦Proxy,拦截整个对象的操作截对象的单个属性
| 对象属性监听 | 无法监听新增/删除属性,需 | 原生支持监听新增/删除属 |
|---|---|---|
| 手动调用Vue.set/Vue.delete | 性,无需手动干预 | |
| 数组监听 | 需重写7个变异方法(push、 | 原生支持监听数组索引、长度 |
| pop等),无法监听索引/长 | 修改及所有方法调用,无需重 | |
| 度修改 | 写 |
支持数据类型仅支持普通对象、数组,不支支持普通对象、数组、Map、持Map、Set等ES6集合Set、WeakMap、WeakSet
等多种类型
依赖收集粒度基于Dep类,每个属性对应一基于targetMap映射,粒度更个Dep,存储依赖的Watcher细,依赖存储更高效,支持自
动去重
| 内存泄漏风险 | 手动维护依赖关系,若组件销 | 使用WeakMap存储响应式对 |
|---|---|---|
| 毁时未清理Watcher,易出现 | 象映射,对象销毁时依赖自动 | |
| 内存泄漏 | 回收,降低内存泄漏风险 |
20. Vue3在编译过程中的优化措施(提升运行时性能)
Vue3的编译系统(核心包: @vue/compiler-core、 @vue/compiler-dom)在解析、优化、生成三个阶段均引入了针对性优化,最终目的是减少运行时虚拟DOM对比和DOM操作的开销,核心优
化措施如下:
- PatchFlags(补丁标记)优化:
- 原理:编译阶段标记模板中的动态节点及其动态类型(如动态文本、动态class、动态style、动态
子节点等),生成 render 函数时,将标记作为参数传入 createVNode;
- 效果:运行时 patch(虚拟DOM对比)阶段,仅针对标记的动态类型进行对比,忽略静态内容,
大幅减少对比次数。例如:标记为“动态文本”的节点,仅对比文本内容,不检查属性、子节点等。
- 静态提升(Static Hoisting):
- 原理:将模板中的静态节点(如 <div>静态文本</div>)或静态根节点(包含多个静态节点的
父节点)提升到 render 函数外部,生成静态VNode常量;
- 效果:避免每次渲染时重新创建静态VNode,减少内存占用和创建开销;运行时 patch 阶段直接
跳过静态节点的对比,提升渲染效率。
- 预字符串化(Pre-stringification):
- 原理:对于包含大量静态内容的节点(如复杂的静态HTML片段),编译时直接将其转换为字符
串,而非多个VNode节点;
- 效果:减少VNode的创建数量,运行时通过 innerHTML 直接插入静态内容,比逐个创建VNode
再渲染更高效。
全站分卷索引 · 12 卷
- 1第 1 卷
- Vue 核心知识点深度解析
- 1. Vue3核心源码精读
- • 核心架构:分为响应式系统( reactivity)、编译系统( compiler)、运行时系统
- • 响应式核心:基于 Proxy 实现响应式,源码核心在 @vue/reactivity 包,包含 effect
- • 组件渲染:采用 VNode(虚拟DOM)描述节点,通过 createVNode 创建虚拟节点, patch
- • 组合式API: setup 函数作为入口, ref(原始类型响应式)、 reactive(对象类型响应
- • 编译优化:引入 PatchFlags(补丁标记)和 StaticNode(静态节点),编译阶段标记动态
- 2. Vuex核心源码精读
- • 核心架构:基于单向数据流设计,核心模块包括 Store(核心类,实例化时初始化状态)、
- • 核心原理:
- 3. Pinia核心源码精读
- • 核心原理:
- 2第 2 卷
- 6. Vue中的依赖收集:触发场景与机制
- 一、依赖收集的触发场景
- 二、依赖收集的核心机制
- • 每个响应式对象的每个属性,对应一个 Dep 类(依赖容器),存储该属性对应的 Watcher
- • 采用“靶心-属性-副作用”的映射关系: WeakMap<响应式对象, Map<属性名,
- • 访问属性时,触发 Proxy 的 get 拦截,调用 track 函数,沿上述映射关系,将当前活跃
- 7. Object.defineProperty的缺点 & Vue3选择Proxy的原因
- 一、Object.defineProperty的潜在缺点/限制
- ◦ 该API只能对已存在的属性进行拦截( get / set),无法感知对象新增属性(如
- ◦ Vue2中需通过 Vue.set / this.$set、 Vue.delete / this.$delete 手动触发响应式
- ◦ Vue2中通过重写数组的7个变异方法(push、pop、shift、unshift、splice、sort、reverse)
- ◦ 若要实现对象全属性响应式,需递归遍历对象的所有属性(包括嵌套对象),对每个属性调用
- 3第 3 卷
- ◦ 示例: <input v-model="msg"> 会被编译为 <input :value="msg"
- 二、不同场景的实现细节
- • 表单元素: v-model 根据元素类型自动匹配属性和事件(文本框: value + input;复选
- • 自定义组件: v-model 是 modelValue prop 和 update:modelValue 事件的语法糖,父
- 9. Vue数据变化时视图的更新机制(即时/异步)
- 一、核心原因
- 二、视图更新的具体机制
- ◦ Vue2:基于 Promise.then(微任务)实现异步队列,兼容环境下会降级为 setTimeout
- ◦ Vue3:基于 queuePostFlushCb 函数,优先使用 Promise.then,其次是
- 10. Vue对象/数组的属性变化监听实现原理
- 一、对象属性变化的监听原理
- 二、数组属性变化的监听原理
- 4第 4 卷
- ◦ 当组件首次进入 keep-alive 时,执行组件的创建生命周期( created、 mounted),
- ◦ 当组件被切换(隐藏)时,Vue不会销毁组件实例,而是将其从DOM中移除,组件状态保留在
- ◦ 当组件再次被切换(显示)时,从 cache 中取出对应的组件实例VNode,重新渲染到DOM
- ◦ max:数字,设置缓存上限,当缓存数量超过 max 时,按照LRU策略删除最久未使用的组件
- ◦ 缓存组件新增两个生命周期: activated(组件激活时触发)、 deactivated(组件失
- 三、具体缓存的内容
- 12. $nextTick方法:原理与用途
- 一、 $nextTick的核心原理
- ◦ 兼容处理:若环境不支持Promise,使用 MutationObserver(微任务),再降级为
- 二、 $nextTick的常见用途
- ◦ 示例:
- ◦ 场景:使用 v-if 控制组件显示隐藏,需要在组件显示后执行初始化逻辑(如第三方插件初始
- 5第 5 卷
- • 解决状态混乱问题:在大型应用中,若组件状态分散管理,会导致状态来源不明确、修改不可控、
- • 提升开发效率:统一的状态管理规范,让团队协作更高效,新开发者可快速理解状态的流转逻辑,
- • 增强应用可维护性:状态与组件解耦,当业务逻辑变更时,只需修改Vuex的Action/Mutation,无
- • 支持高级特性:内置支持状态持久化(配合插件)、模块化拆分、命名空间隔离等高级特性,满足
- 14. Vuex与localStorage在状态管理的不同用途和特性对比
- 一、核心特性对比
- 二、不同用途
- 三、最佳实践
- • 两者结合使用:Vuex负责运行时状态管理,localStorage负责状态持久化,例如:
- • 避免滥用:
- 一、本质区别
- 二、Vuex的核心优势
- 6第 6 卷
- 7第 7 卷
- 8第 8 卷
- 9第 9 卷
- 10第 10 卷
- 11第 11 卷
- 12第 12 卷