第 8 卷
- 效果:减少函数创建开销,同时确保VNode的事件属性引用稳定,避免因函数引用变化导致的不
必要重渲染。
- v-once指令优化:
- 原理:标记为 v-once 的节点,编译时标记为“仅渲染一次”的静态节点,首次渲染后缓存
VNode,后续不再重新渲染;
- 效果:适用于静态内容或初始化后不再变化的动态内容,减少重复渲染开销。
- 动态指令参数优化:
- 原理:对于动态指令参数(如 v-bind:[key]="value"),编译时分析可能的参数值范围,
生成更高效的运行时代码;
- 效果:避免运行时对所有可能的指令参数进行遍历检查,提升动态指令的解析效率。
- Tree-shaking支持:
- 原理:编译时根据模板内容,只导入使用到的运行时API(如 createVNode、
patchProps),未使用的API不会被打包;
- 效果:减小打包体积,提升应用加载速度。
21. Vue3在性能上优于Vue2的核心原因
Vue3的性能优势是“响应式系统升级+编译优化+运行时优化”多维度协同的结果,核心原因如下:
- 响应式系统更高效:
- 用Proxy替代Object.defineProperty,减少初始化开销:Vue2需递归遍历对象所有属性并逐个封
装,Vue3采用懒加载机制,仅在访问嵌套对象时才进行Proxy封装,初始化速度提升约50%;
- 精准依赖收集:Vue3的依赖收集粒度更细,仅收集实际使用的属性对应的副作用,避免Vue2
中“属性依赖全量更新”的冗余开销,状态变化时只触发相关组件重渲染。
- 编译阶段深度优化:
- PatchFlags减少虚拟DOM对比开销:运行时仅对比标记的动态内容,静态内容直接跳过,对比效率
提升显著;
- 静态提升、预字符串化减少VNode创建开销:静态内容复用VNode或直接转为字符串插入,减少内
存占用和渲染时间;
- 缓存事件处理函数避免不必要重渲染:稳定的函数引用确保VNode属性不频繁变化,减少重渲染触
发。
- 虚拟DOM与diff算法优化:
- diff算法优化:针对数组diff,Vue3引入“最长递增子序列”算法,减少节点移动操作(如列表排
序场景),DOM操作次数显著减少;Vue2的diff算法采用“双指针遍历”,在列表重排时移动操作较多。
- 运行时体积优化:
- Monorepo架构支持按需导入:应用可只导入使用到的模块(如仅导入响应式模块、编译模块),
未使用的功能(如选项式API的部分辅助函数)不打包,打包体积比Vue2减少约30%;
- Tree-shaking清除冗余代码:编译时自动剔除未使用的运行时API,进一步减小包体积,提升加载
速度。
- 其他运行时优化:
- 组件渲染优化:支持多根节点组件,减少不必要的容器节点嵌套,降低DOM层级和渲染开销;
- 异步组件优化:新增Suspense组件,支持异步组件的并行加载和状态统一管理,减少等待时间;
- 内存管理优化:使用WeakMap存储响应式依赖,对象销毁时依赖自动回收,减少内存泄漏风险,
长期运行更稳定。
22. Vue3中watch和watchEffect的区别 & 适用场景
一、核心区别
| 对比维度 | watch | watchEffect |
|---|---|---|
| 依赖指定方式 | 显式指定监听目标(如单个响 | 隐式收集依赖,自动监听回调 |
| 应式数据、多个响应式数据、 | 函数中使用的所有响应式数据 |
对象属性)
| 初始化执行 | 默认不执行,需通过 | 默认初始化执行一次,自动收 |
|---|---|---|
| immediate: true配置才 | 集回调中的依赖(类似 | |
| 会初始化执行一次 | immediate: true的 |
watch)
| 参数获取 | 回调函数接收三个参数:新值 | 回调函数仅接收清理函数 |
|---|---|---|
| (newVal)、旧值 | (onInvalidate),无法直接 | |
| (oldVal)、清理函数 | 获取新旧值,需手动缓存旧值 |
(onInvalidate),可对比新旧值差异
监听粒度可精确到对象的单个属性监听回调中所有访问的响应式
| 使用复杂度 | 略高,需手动指定监听目标, | 更简洁,无需指定监听目标, |
|---|---|---|
| 配置必要参数(如 | 直接编写业务逻辑,自动收集 | |
| immediate、deep) | 依赖 |
二、适用场景
- watch适用场景:
- 需要精确监听某个/某些特定响应式数据的场景(如仅监听用户ID变化,触发接口请求);
- 需要对比新旧值差异的场景(如监听表单输入值变化,判断输入是否符合规则,需用到旧值和新
值);
- 不需要初始化执行,仅在数据变化时触发逻辑的场景(如用户修改设置后,保存修改记录);
- 需要深度监听对象/数组内部变化的场景(通过 deep: true 配置,如监听 state.user 对象的
所有属性变化)。
- watchEffect适用场景:
- 需要监听多个响应式数据,且只要其中任意一个变化就触发逻辑的场景(如表单多个字段联动校
验);
- 需要初始化执行一次,之后自动响应数据变化的场景(如页面加载时获取初始数据,之后监听筛选
条件变化重新获取数据);
- 无需对比新旧值,只需根据响应式数据变化执行副作用(如修改DOM、发送请求、操作缓存)的场
景;
- 业务逻辑简单,依赖关系明确且无需精确控制监听粒度的场景(如根据多个状态切换页面标
题)。
三、示例对比
Code block
1// watch示例:监听用户名称变化,对比新旧值
| 2 | const state = reactive({ user: { name: '张三', age: 20 } }) |
|---|---|
| 3 | watch( |
| 4 | () => state.user.name, |
| 5 | (newVal, oldVal, onInvalidate) => { |
| 6 | console.log(`名称从${oldVal}改为${newVal}`) |
| 7 | //清理副作用(如取消未完成的请求) |
| 8 | onInvalidate(() => { /*清理逻辑*/ }) |
全站分卷索引 · 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 卷