[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fmTn6_MEgX0nWeVqe2hysJvR7BSKUuwVn8NnZ_J7PzOc":3},{"code":4,"message":5,"data":6},200,"成功",{"id":7,"createdAt":8,"title":9,"content":10,"summary":11,"image":12,"uid":13,"user":14,"categoryId":21,"category":22,"subCategoryId":24,"subCategory":25,"comments":27,"status":17,"reason":12,"notice":12,"visitCount":28,"commentCount":29,"keywords":30},193,"2026-09-02T10:17:33.09Z","Vue高级面试题","# Vue高级面试题\n\n## 1. Vue 3 相比 Vue 2 的核心改进有哪些？\n\n**答案：**\n\n- 使用 `Proxy` 重构响应式，解决 `Object.defineProperty` 无法监听数组、新增和删除属性的问题。\n- 全新 Composition API，解决大型项目中 Options API 碎片化的问题。\n- 支持 TypeScript 全量类型推导。\n- 打包体积更小，支持 Tree Shaking。\n- 性能提升：更新更快，减少无用渲染。\n- 新增 `Teleport`、`Suspense`、`Fragment`，支持多根节点。\n- 全新异步组件、自定义渲染器。\n\n## 2. Vue 3 Proxy 相比 Vue 2 defineProperty 有哪些优势？\n\n**答案：**\n\n- 可监听数组变化，包括增删、下标修改和 `length` 变化。\n- 可监听对象新增、删除属性。\n- 可监听 `Map`、`Set` 集合类型。\n- 一次性代理整个对象，无需递归遍历所有属性。\n- 支持更多拦截行为，例如 `has`、`deleteProperty` 等。\n\n## 3. Vue 3 响应式原理整体流程？\n\n**答案：**\n\n数据初始化 → 使用 `reactive` 创建 `Proxy` 代理 → 组件渲染触发 `getter` 收集依赖 → 数据修改触发 `setter` → `trigger` 触发组件更新 → `patch` 更新 DOM。\n\n## 4. ref 和 reactive 的区别？\n\n**答案：**\n\n- `ref`：支持基本类型和引用类型。\n- `reactive`：主要用于处理对象、数组等引用类型。\n- `ref` 通过 `.value` 访问，底层对象依然会通过 `reactive` 转换为响应式对象。\n- `reactive` 使用 `Proxy` 代理，无需通过 `.value` 访问。\n- `ref` 的本质：基本类型无法被 `Proxy` 代理，所以需要包装成对象。\n\n## 5. 为什么 ref 需要 `.value`？\n\n**答案：**\n\n`Proxy` 只能代理对象，无法代理字符串、数字等基本类型。`ref` 会将原始值包装成 `{ value: xxx }` 对象，从而实现响应式。\n\n## 6. toRef 和 toRefs 的区别？\n\n**答案：**\n\n- `toRef`：单独取出对象某个属性生成 `ref`，并与原对象保持关联。\n- `toRefs`：批量将 `reactive` 对象所有属性转换为 `ref`。\n- 重点：不会丢失响应式，解构赋值时很有用。\n\n## 7. reactive 解构为什么会丢失响应式？\n\n**答案：**\n\n解构赋值取出的是原始值，脱离了 `Proxy` 代理对象，因此不再具备响应式。必须使用 `toRefs` 或 `toRef` 进行解构。\n\n## 8. computed 缓存原理？\n\n**答案：**\n\n`computed` 内部有 `dirty` 标记：\n\n- 依赖未变化：`dirty = false`，直接返回缓存值。\n- 依赖变化：`dirty = true`，重新计算。\n- 所以多次访问时只会执行一次计算。\n\n## 9. computed 和 watch 的区别？\n\n**答案：**\n\n- `computed`：依赖缓存、同步、纯计算，不支持异步副作用。\n- `watch`：无缓存，支持异步操作，监听变化后执行副作用。\n\n## 10. watch、watchEffect 的区别？\n\n**答案：**\n\n- `watch`：需要手动指定监听源，可获取新值和旧值，默认不立即执行。\n- `watchEffect`：自动收集依赖，立即执行，无法获取 `oldValue`。\n\n## 11. watchEffect 如何停止监听？\n\n**答案：**\n\n`watchEffect` 会返回一个 `stop` 函数，手动调用即可停止监听；组件卸载时，监听也会自动停止。\n\n```js\nconst stop = watchEffect(() => {\n  console.log('监听中')\n})\n\nstop()\n```\n\n## 12. Vue 3 生命周期和 Vue 2 的区别？\n\n**答案：**\n\n- 组合式 API 使用 `onMounted`、`onUpdated` 等函数式生命周期。\n- 取消 `beforeCreate` 和 `created`，相关逻辑可以直接写在 `setup` 最顶部。\n- 新增 `onRenderTracked`、`onRenderTriggered` 等调试钩子。\n\n## 13. setup 执行时机？\n\n**答案：**\n\n`setup` 在 `beforeCreate` 之前执行，此时组件实例尚未创建，无法访问 `this`。\n\n## 14. setup 中为什么没有 this？\n\n**答案：**\n\n`setup` 执行时机早于组件实例创建，`this` 不存在；同时，Composition API 的设计理念就是脱离 `this`。\n\n## 15. Vue 3 组件通信方式有哪些？\n\n**答案：**\n\n- 父子通信：`props`、`defineProps`\n- 子传父：`emit`、`defineEmits`\n- 父组件访问子组件：`expose`、`defineExpose`\n- 跨级通信：`provide`、`inject`\n- 全局属性：`globalProperties`\n- 状态管理：Pinia\n- 事件总线：`mitt`，替代 Vue 2 的 EventBus\n\n## 16. defineProps、defineEmits 原理？\n\n**答案：**\n\n`defineProps` 和 `defineEmits` 是 Vue 3 的编译期宏函数，无需导入，仅在 `\u003Cscript setup>` 语法糖中生效，编译阶段会被直接解析，无运行时开销。\n\n## 17. provide/inject 响应式如何保证？\n\n**答案：**\n\n`provide` 传递 `ref` 或 `reactive` 数据即可保持响应式；普通数据不会自动响应。也可以通过 `readonly` 防止子组件篡改。\n\n```js\nprovide('state', readonly(state))\n```\n\n## 18. Vue 3 为什么废弃 EventBus？\n\n**答案：**\n\nVue 2 的 EventBus 基于 Vue 实例，多组件混用容易造成事件残留、重复监听和内存泄漏。Vue 3 不再提供基于 Vue 实例的事件总线，推荐使用独立的轻量事件总线，例如 `mitt`。\n\n## 19. Pinia 相比 Vuex 的优势？\n\n**答案：**\n\n- 去除 `mutations`，可以直接修改 `state`。\n- 完整的 TypeScript 类型推导。\n- 模块扁平化，无需嵌套 `modules`。\n- 体积更小，API 更简洁。\n- 支持模块化和热更新。\n\n## 20. Vue 3 diff 算法优化（核心高级题）\n\n**答案：**\n\nVue 3 使用最长递增子序列优化移动逻辑：\n\n- 头尾对比预处理。\n- 生成新老节点的 `key` 映射表。\n- 通过最长递增子序列，最小化 DOM 移动次数。\n- 相比 Vue 2 的乱序 diff，性能有较大提升。\n\n## 21. Vue 3 虚拟 DOM 相比 Vue 2 有哪些优化？\n\n**答案：**\n\n- `PatchFlag`：静态标记，只更新动态节点。\n- `hoistStatic`：静态节点提升，不参与更新。\n- `cacheHandlers`：事件缓存。\n- 减少 VDOM 创建开销。\n\n## 22. PatchFlag 原理？\n\n**答案：**\n\n编译时给动态节点打标记，例如文本、`class`、`style` 和 `props`。diff 时只对比标记过的动态内容，静态内容直接跳过，极大提升 diff 速度。\n\n## 23. Vue 3 为什么可以多根节点？\n\n**答案：**\n\nVue 3 编译阶段支持 `Fragment`。`Fragment` 是一个虚拟根节点，不渲染真实 DOM，所以支持多根模板。\n\n## 24. Teleport 原理和使用场景？\n\n**答案：**\n\n`Teleport` 可以将组件 DOM 挂载到任意 DOM 位置，脱离父组件层级、`overflow`、`z-index` 等限制。\n\n常用于弹窗、悬浮层、全局提示等场景。\n\n## 25. Suspense 的作用？\n\n**答案：**\n\n`Suspense` 用于处理异步组件加载，加载中显示 `fallback`，加载完成后渲染组件；常用于路由懒加载和异步组件。\n\n## 26. Vue 3 异步组件写法？\n\n**答案：**\n\n```js\nconst MyComp = defineAsyncComponent(() => import('./comp.vue'))\n```\n\n## 27. Vue 3 样式穿透 `:deep()` 原理？\n\n**答案：**\n\n`scoped` 样式会给当前组件 DOM 添加唯一的 `data-v-xxx` 属性，从而限制样式作用范围。\n\n`:deep()` 让内部选择器不携带当前组件的 scoped 唯一属性，从而可以修改子组件内部样式。\n\n```css\n:deep(.child-class) {\n  color: red;\n}\n```\n\n## 28. Vue 3 性能优化实战手段？\n\n**答案：**\n\n- `v-once`：静态节点只渲染一次。\n- `v-memo`：缓存动态节点。\n- 拆分组件，减少无效渲染。\n- 使用 `computed` 缓存计算结果。\n- 使用异步组件和路由懒加载。\n- 大型列表使用虚拟列表。\n\n## 29. v-memo 的作用？\n\n**答案：**\n\n`v-memo` 可以缓存模板节点。当依赖值不变时，跳过整段 diff，适合长列表和复杂模板，可以明显提升渲染性能。\n\n## 30. Vue 3 响应式丢失场景及解决方案？\n\n**答案：**\n\n- 解构 `reactive` 对象会丢失响应式。  \n  解决方案：使用 `toRefs` 或 `toRef`。\n- 直接替换 `reactive` 整个对象会导致响应式丢失。  \n  解决方案：使用 `Object.assign`，或者使用 `ref` 管理整个对象。\n- 普通变量接收 `ref` 值会丢失响应式。  \n  解决方案：必须保留 `.value`。\n- 函数参数解构可能导致响应式丢失。  \n  解决方案：提前使用 `toRefs`。\n","这里给大家推荐几十道有关vue的高级面试题，希望对大家有帮助.","",525978185445445,{"phone":15,"userId":13,"nickName":16,"vipType":17,"avatar":18,"sign":19,"createdAt":20},"16100000003","上班墨鱼",1,"https://image.xinwei.ltd/bbd06233d9b5c67c9f8ddd35b63cb81f1710561355517.jpeg","没有什么缺点，大家低调点","2024-03-16T00:30:44.932Z",2,{"id":21,"name":23},"IT技术",32,{"id":24,"name":26,"parentId":21},"前端",[],10,0,"vue,vue面试题,面试题,前端面试题,vue2,vue3,vue 3,vue 3.x, vue 2, vue2.x"]