第 2 卷
- 适合动态组件:对于渲染结构不固定、需要动态生成标签/属性的场景(如自定义表单、动态菜
单),JSX比template更简洁;
- 无缝衔接组合式API:在Vue3组合式API中,JSX可直接使用组件内的响应式数据,无需额外指令;
- React开发者友好:熟悉React的开发者可快速上手Vue的JSX,降低跨框架学习成本。
6. Vue中的依赖收集:触发场景与机制
一、依赖收集的触发场景
依赖收集是Vue响应式系统的核心,只有在副作用函数(Effect)执行时,访问响应式数据,才会触发依赖收集,常见场景包括:
- 组件渲染:组件的 render 函数(或 setup 函数中返回的渲染函数)执行时,访问响应式数据
(state、props等),会触发依赖收集;
2.computed 计算属性:初始化 computed 时,其内部的求值函数执行,访问响应式数据,触发依赖收集;
3.watch / watchEffect: watch 监听的目标数据被访问(或 watchEffect 的回调函数执行时访问响应式数据),触发依赖收集;
- 自定义 effect:通过 vue 暴露的 effect 函数创建自定义副作用,执行时访问响应式数据,
触发依赖收集。
二、依赖收集的核心机制
Vue2和Vue3的依赖收集机制核心思路一致,细节略有差异,整体流程如下:
通用核心流程
- 副作用函数包装:将需要执行的逻辑(如组件渲染、computed求值)包装为 Effect 副作用函
数;
- 激活Effect:执行副作用函数前,将当前 Effect 标记为“活跃状态”(全局唯一的当前副作
用);
- 访问响应式数据:副作用函数执行时,访问响应式数据的属性(如 obj.msg);
- 收集依赖:响应式数据的拦截器(Vue2: Object.defineProperty;Vue3: Proxy)感知
到属性被访问,将当前活跃的 Effect 收集到该属性的“依赖集合”中;
- 取消激活:副作用函数执行完毕后,取消当前 Effect 的活跃状态。
• 每个响应式对象的每个属性,对应一个 Dep 类(依赖容器),存储该属性对应的 Watcher
- 访问属性时,触发 get 拦截器,调用 Dep.depend(),将当前 Watcher 添加到 Dep 中。
Vue3 具体实现
• 采用“靶心-属性-副作用”的映射关系: WeakMap<响应式对象, Map<属性名,
Set<Effect>>>;
• 访问属性时,触发 Proxy 的 get 拦截,调用 track 函数,沿上述映射关系,将当前活跃
Effect 添加到对应属性的 Set 集合中;
- 依赖集合使用 Set,自动去重,避免重复收集相同的 Effect。
7. Object.defineProperty的缺点 & Vue3选择Proxy的原因
一、Object.defineProperty的潜在缺点/限制
Object.defineProperty 是Vue2实现响应式的核心API,存在以下固有缺陷:
- 无法监听对象属性的新增/删除:
◦ 该API只能对已存在的属性进行拦截( get / set),无法感知对象新增属性(如
obj.newKey = 123)或删除属性(如 delete obj.key);
◦ Vue2中需通过 Vue.set / this.$set、 Vue.delete / this.$delete 手动触发响应式
更新,侵入性强。
- 无法监听数组的原生方法与索引变化:
- 无法感知数组索引修改(如 arr[0] = 123)和数组长度修改(如 arr.length = 0);
◦ Vue2中通过重写数组的7个变异方法(push、pop、shift、unshift、splice、sort、reverse)
来实现响应式,对于非变异方法(如slice)无法监听,索引修改仍需手动触发。
- 遍历对象性能较差:
◦ 若要实现对象全属性响应式,需递归遍历对象的所有属性(包括嵌套对象),对每个属性调用
Object.defineProperty,性能随对象复杂度提升而下降;
- 无法批量处理对象属性,只能逐个拦截。
- 不支持Map、Set等集合类型:
◦ 该API仅适用于普通对象(Object),对于ES6新增的Map、Set、WeakMap等集合类型,无法
有效实现拦截与响应式。
二、Vue3选择Proxy的原因
◦ Proxy 拦截的是整个对象,而非单个属性,通过 set 拦截器可监听属性新增,
deleteProperty 拦截器可监听属性删除,无需手动干预;
- 原生支持数组监听:
◦ 可直接监听数组的索引修改、长度修改,以及所有数组方法(无需重写变异方法),通过
set、 get 拦截器即可感知数组变化;
- 性能更优,支持懒拦截:
◦ 无需递归遍历嵌套对象,可在 get 拦截器中按需对嵌套对象进行代理(懒加载),减少初始化
时的性能开销;
- 可批量拦截对象的所有属性,无需逐个处理。
- 支持更多数据类型:
◦ 不仅支持普通对象,还支持Map、Set、WeakMap、WeakSet等ES6集合类型,以及函数等对
象类型;
- 拦截能力更强:
◦ Proxy 提供了13种拦截器方法(如 has、 ownKeys、 apply 等),远超
Object.defineProperty 的 get / set 拦截,能实现更复杂的响应式逻辑。
补充: Proxy 唯一的不足是不支持IE浏览器,但Vue3已放弃IE兼容,专注于现代浏览器,因此可放心使用。
8. Vue双向数据绑定的基本原理
Vue的双向数据绑定(核心指令 v-model)是单向数据绑定(数据→视图) + 事件监听(视图→数据)的封装,实现了“数据变化更新视图,视图操作更新数据”的双向联动。
一、核心原理拆解
- 单向数据绑定(数据→视图):
- 底层依赖Vue的响应式系统(Vue2: Object.defineProperty;Vue3: Proxy);
◦ 当数据(如组件的 data、 props)发生变化时,响应式系统会触发依赖更新(如组件
Watcher / Effect),执行 render 函数生成新的VNode,通过 patch 函数对比虚拟 DOM,最终更新真实DOM(视图)。
- 事件监听(视图→数据):
- 底层依赖DOM事件监听(如 input、 change 事件);
- v-model 指令会自动为表单元素绑定对应的事件,并在事件回调中更新数据;
全站分卷索引 · 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 卷