第 9 卷
15const { name, age } = state.user
| 16 | console.log(`当前用户:${name},年龄:${age}`) |
|---|---|
| 17 | //清理副作用 |
| 18 | onInvalidate(() => { /*清理逻辑*/ }) |
| 19 | }) |
23. Vue3中reactive、ref的区别及使用场景
一、核心区别
| 对比维度 | reactive | ref |
|---|---|---|
| 适用数据类型 | 仅支持对象/数组类型(引用 | 主要支持原始类型,也可支持 |
| 类型),不支持原始类型 | 对象/数组(内部会自动转为 | |
| (string、number、 | reactive代理) |
boolean等)
| 访问方式 | 直接访问属性(如 | 需通过.value属性访问和 |
|---|---|---|
| state.name),无需额外 | 修改(如nameRef.value | |
| 包装 | = '新值');模板中使用时 |
自动解包,无需 .value
响应式实现原理直接通过Proxy代理目标对封装为包含 value 属性的对象,拦截对象的属性操作象,对 value 属性使用
Proxy实现响应式(原始类型)或转为reactive(引用类
型)
| 解构赋值影响 | 直接解构会丢失响应式(如 | 解构后仍保持响应式(如 |
|---|---|---|
| const { name } = | const { value: name } | |
| state,name不再是响应 | = nameRef,name需通 | |
| 式),需使用toRefs辅助 | 过.value访问,仍为响应 | |
| 函数 | 式) | |
| 类型推导(TS) | 对对象类型的推导更自然,可 | 原始类型的推导更精准,引用 |
| 直接推导属性类型 | 类型需通过Ref<T>显式声 |
明类型
二、使用场景
项);
- 不需要解构赋值,直接通过对象属性访问状态的场景,避免使用 toRefs 的额外开销。
- ref适用场景:
- 存储单个原始类型状态(如单个字符串、数字、布尔值,如 const count = ref(0)、
const isShow = ref(false));
- 需要将响应式状态传递给函数,且希望保持响应式的场景(ref通过 .value 传递,不会丢失响应
式;reactive直接传递对象属性会丢失响应式);
- 模板中使用的单个响应式状态(自动解包 .value,使用更简洁);
- 需要解构赋值且保持响应式的场景(无需使用 toRefs,直接解构 .value 即可)。
三、最佳实践
- 复杂对象/数组状态用 reactive,单个原始类型状态用 ref;
- 若需要解构 reactive 对象的属性并保持响应式,使用 toRefs(如 const { name, age
} = toRefs(state));
- ref存储引用类型时(如 const userRef = ref({ name: '张三' })),修改深层属性仍
需通过 .value(如 userRef.value.name = '李四'),内部会自动转为reactive代理;
- TypeScript环境下,ref的原始类型可自动推导(如 const count = ref(0) 推导为
Ref<number>),引用类型建议显式声明(如 const userRef = ref<User>({ name:
'张三' }))。
24. Vue3的Composition API与React的Hooks在设计和用法上的主要不
同
一、设计理念差异
- 核心定位:
- Vue3 Composition API:作为选项式API的补充和增强,核心目标是解决大型组件的“逻辑碎片
化”问题,通过函数组合的方式组织逻辑,保持与Vue原生响应式系统的深度融合;
- React Hooks:是React函数组件的核心特性,彻底替代类组件,通过 Hooks 实现状态管理、生命
周期等功能,核心目标是让函数组件具备类组件的能力,同时简化逻辑复用。
- 与响应式系统的关系:
二、用法核心差异
| 对比维度 | Vue3 Composition API | React Hooks |
|---|---|---|
| 状态定义与访问 | 通过reactive(对象/数 | 通过useState(单个状 |
| 组)或ref(原始类型)定 | 态)或useReducer(复杂 | |
| 义响应式状态,直接访问属性 | 状态)定义状态,通过数组解 | |
| (reactive)或通过.value | 构获取状态和更新函数(如 | |
| 访问(ref),状态变化自动 | const [count, | |
| 响应; | setCount] = |
useState(0)),需调用更新函数触发重渲染;
| 逻辑复用方式 | 通过“组合函数”复用逻辑 | 通过“自定义Hooks”复用逻 |
|---|---|---|
| (如function | 辑(如function | |
| useUser() { const | useUser() { const | |
| state = reactive({}); | [user, setUser] = | |
| ... return state; | useState({}); ... | |
| }),组件内直接调用函数获 | return [user, | |
| 取复用的状态和逻辑,无额外 | setUser]; }),自定义 | |
| 约束; | Hooks必须以“use”开头, |
且只能在函数组件或其他 Hooks顶层调用;
| 生命周期模拟 | 通过onMounted、 | 通过useEffect模拟所有生 |
|---|---|---|
| onUpdated、 | 命周期(如挂载、更新、卸 | |
| onUnmounted等函数模拟 | 载),需通过依赖数组控制执 | |
| 生命周期,可在setup函数 | 行时机(空数组:挂载时执行 | |
| 内任意位置调用,支持多个相 | 一次;无数组:每次渲染执 | |
| 同生命周期钩子(按顺序执 | 行;指定依赖:依赖变化执 | |
| 行); | 行); | |
| 依赖收集 | 自动收集依赖, | 需手动指定依赖数组(如 |
| computed、watch、 | useEffect(() => {}, | |
| watchEffect等API会自动 | [count])),若依赖遗漏会 | |
| 监听使用的响应式状态,无需 | 导致逻辑错误,React 18+支 | |
| 手动指定依赖; | 持自动依赖收集(但仍建议显 |
式指定);
全站分卷索引 · 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 卷