Vue面试题

面试题

Vue2 Vue3 生命周期

  • Vue 实例从创建到销毁的过程就是生命周期,主要钩子包括创建、挂载、更新和销毁四个阶段 。
  • Vue2 常用钩子为 beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、‌beforeDestroy‌、‌destroyed‌。
  • Vue3 中将销毁阶段钩子更名为 ‌beforeUnmount‌ 和 ‌unmounted‌,其余基本保持一致,但执行时机和底层实现有所优化 。

‌Vue 2 和 Vue 3 的响应式原理有什么不同‌

  • Vue2 使用 ‌Object.defineProperty‌ 劫持对象属性的 getter 和 setter 来实现响应式,无法检测对象属性的新增或删除,以及数组索引和长度的变化 。
  • Vue3 改用 ‌Proxy‌ 代理对象,可以直接监听对象属性的增删改查,性能更好且支持更多数据类型 。 数组处理上,Vue 2 重写了 push、pop、splice 等 7 种变异方法来触发更新,而 Vue 3 的 Proxy 能直接拦截数组索引变化

Vue 组件间如何进行通信‌

  • ‌父传子‌:使用 ‌props‌ 属性,支持静态值或动态绑定,数据流是单向的 。
  • ‌子传父‌:子组件通过 ‌$emit‌ 触发事件,父组件监听事件接收参数 。
  • ‌跨级通信‌:使用 ‌provide/inject‌ 依赖注入,或状态管理工具如 ‌Vuex‌、‌Pinia‌。
  • ‌兄弟组件‌:可通过事件中心(Event Bus)或共同父组件中转,Vue 3 中推荐使用状态管理或 props/$emit 组合 。‌‌‌

computed 和 watch 有什么区别,应用场景是什么‌

‌computed‌ 是计算属性,支持缓存,只有依赖数据变化时才重新计算,适合处理复杂的逻辑运算并返回结果 。 ‌watch‌ 是侦听器,不支持缓存,数据变化时直接执行回调,适合执行异步操作或开销较大的任务 。‌‌ Vue3相比Vue2 有哪些主要改进? 答案:

采用Composition API,更灵活的代码组织方式

基于Proxy实现的响应式系统,性能更好,支持数组索引和对象新增属性

重构了虚拟DOM,优化了渲染性能

支持Tree-shaking,减小打包体积

新增了Teleport、Suspense等组件

更好的TypeScript支持

模板语法增强,如多根节点、指令合并等

什么是setup函数?

-setup函数是Composition API的入口点,在组件创建前执行(props解析后)。它接收props和context两个参数,返回的对象会暴露给模板使用。setup函数中不能使用this,因为组件实例尚未创建完成。

ref和reactive的区别是什么?

  • 数据类型 :ref用于包装基本类型数据,reactive用于包装对象类型数据

  • 返回值 :ref返回的是一个带有value属性的对象,reactive返回的是原始对象的代理

  • 访问方式 :访问ref包装的数据需要通过.value,在模板中会自动解包

  • 修改方式 :对ref包装的对象进行修改,需要修改.value属性;对reactive包装的对象可以直接修改属性

  • 响应式深度 :ref对对象类型数据会自动转换为reactive

computed和watch的区别是什么?

  • 用途 :computed用于计算派生值,watch用于监听数据变化并执行副作用

  • 缓存机制 :computed有缓存机制,只有依赖变化时才会重新计算;watch没有缓存

  • 返回值 :computed必须有返回值,watch可以没有

  • 异步操作 :computed不能执行异步操作,watch可以

  • 触发时机 :computed在依赖变化时立即计算,watch默认在数据变化后执行

什么是toRef和toRefs?

  • toRef用于将响应式对象的某个属性转换为ref

  • toRefs用于将响应式对象的所有属性转换为ref对象,并返回一个包含这些ref的普通对象

  • 这两个函数常用于在解构响应式对象时保持响应性

provide和inject的作用是什么?

provide和inject用于实现跨层级组件通信。父组件通过provide提供数据,子组件或孙组件通过inject注入数据。这种方式可以避免props drilling(props层层传递)的问题。

什么是作用域插槽?

作用域插槽允许子组件向父组件传递数据,父组件可以根据这些数据来渲染插槽内容。在Vue3中,作用域插槽通过v-slot指令和slotProps实现。

什么是响应式失效?如何解决?

  • 响应式失效是指当修改响应式数据时,视图没有更新。常见原因包括:

  • 直接修改了数组的索引或长度

  • 给对象新增属性时没有使用正确的方法

  • 在setup函数中返回的不是响应式数据 解决方法:

  • 使用数组的push、pop等方法,或使用toRefs将数组转换为ref

  • 给对象新增属性时使用Vue.set或确保对象是reactive创建的

  • 确保setup函数返回的是响应式数据

Vue3中的响应式代理有哪些局限性?

无法直接检测对象的新增属性(需确保对象是 reactive 创建的或手动触发更新)

无法直接检测数组的索引和长度变化(需使用数组方法或 Vue.set 变体)

无法直接检测到Map、Set的某些变化(需手动触发更新或使用 reactive 包裹)

深度响应式可能影响性能(可用 shallowReactivemarkRaw 优化)

Vue3的虚拟DOM有哪些改进?

优化了diff算法,减少了比较次数

支持静态提升,将静态节点提升到渲染函数之外

支持PatchFlag,标记动态节点的变化类型

支持缓存事件处理函数,避免不必要的重新创建

支持block tree,提高diff效率

如何优化Vue3的渲染性能?

使用v-once指令缓存静态内容

使用v-memo指令缓存动态内容

避免不必要的响应式数据

使用shallowReactive和shallowRef减少响应式开销

合理使用组件拆分,提高组件复用性

使用keep-alive缓存组件状态

优化大型列表渲染(如虚拟滚动)

什么是v-memo指令?

v-memo指令用于缓存模板中的一部分内容,只有当依赖的数据变化时才会重新渲染。它接收一个依赖数组,当数组中的任何一个元素变化时,才会重新渲染缓存的内容。v-memo可以用于优化频繁渲染的列表或复杂组件

Vue3中的自定义指令有哪些变化?

Vue3中的自定义指令使用钩子函数而不是对象字面量

钩子函数与组件生命周期钩子类似,包括beforeMount、mounted、beforeUpdate、updated、beforeUnmount、unmounted

指令的binding参数包含更多信息,如instance、value、oldValue等

支持传递多个值给指令

什么是Teleport组件?

Teleport组件用于将组件的内容渲染到DOM中的指定位置,而不是当前组件的位置。这对于模态框、通知等组件非常有用,可以避免CSS样式的干扰。

什么是Suspense组件?

Suspense组件用于处理异步组件的加载状态。它可以定义一个fallback内容,在异步组件加载完成前显示。Suspense还支持嵌套的异步依赖。示例:

Pinia和Vuex的区别是什么?

Pinia是Vue3推荐的状态管理库,Vuex是Vue2的官方状态管理库

Pinia没有mutations,直接通过actions修改状态

Pinia支持TypeScript,类型推断更好

Pinia的API更简洁,易于使用

Pinia支持多个store实例,Vuex通常只有一个store实例

Pinia的体积更小,性能更好

Pinia支持devtools,调试更方便

如何在Pinia中定义一个store?

可以使用defineStore函数定义一个store。它接收两个参数:store的名称和一个包含state、actions、getters的对象。state是一个函数,返回初始状态;actions是修改状态的方法;getters是计算属性。

如何在组件中使用Pinia的store?

可以使用useStore函数(需要传入store的定义)在组件中获取store实例,然后通过store实例访问state、getters和actions。

什么是状态持久化?如何实现?

状态持久化是指将状态保存到本地存储(如localStorage、sessionStorage)中,以便在页面刷新或重新打开时恢复状态。可以使用pinia-plugin-persistedstate等插件实现,也可以手动在actions中保存状态。

如何在Pinia中实现模块化?

Pinia本身支持模块化,每个store都是一个独立的模块。可以根据功能将状态分为多个store,如userStore、productStore等。

Vue Router 4有哪些变化?

支持Composition API,可以在setup中使用useRouter、useRoute等钩子

路由配置简化,不再需要new Router,而是使用createRouter

支持History API的多种模式,包括createWebHistory、createWebHashHistory、createMemoryHistory

支持动态路由匹配,如/user/:id

支持导航守卫,包括全局守卫、路由守卫、组件守卫

支持路由元信息

支持路由懒加载

什么是路由守卫?

路由守卫是Vue Router提供的一种机制,用于在路由切换过程中执行一些操作,如验证权限、加载数据等。路由守卫包括:

全局守卫 :beforeEach、beforeResolve、afterEach

路由守卫 :beforeEnter

组件守卫 :beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave 示例(全局守卫)

如何实现路由懒加载?

路由懒加载是指将路由组件按需加载,而不是在初始加载时全部加载。在Vue Router 4中,可以使用动态import语法实现路由懒加载

如何优化大型列表的渲染?

使用虚拟滚动库(如vue-virtual-scroller),只渲染可视区域内的列表项

使用v-memo指令缓存列表项

避免在列表项中使用复杂的计算属性

合理设置key,避免不必要的DOM操作

懒加载列表数据,分页加载

避免在列表渲染时进行 heavy 计算

什么是组件按需加载?

组件按需加载是指将组件拆分为单独的代码块,只在需要时才加载。在Vue3中,可以使用动态import语法和defineAsyncComponent函数实现组件按需加载。这可以减小初始打包体积,提高页面加载速度。

什么是tree-shaking?Vue3是如何支持的?

tree-shaking是一种优化技术,用于移除代码中未使用的部分。Vue3的API设计支持tree-shaking,因为大多数API都是通过ES模块导出的,打包工具(如webpack、rollup)可以分析代码依赖,移除未使用的API。这可以减小打包体积。

Vue3中的TypeScript 支持如何?

Vue3本身是用TypeScript编写的,提供了更好的TypeScript支持。Composition API的设计更符合TypeScript的类型系统,setup函数、ref、reactive等API都有良好的类型推断。此外,Vue3还提供了defineComponent函数,用于定义带类型的组件。

Vue的核心特性有哪些?

答:核心特性主要是这5点:① 数据驱动视图(MVVM思想,数据变视图自动更,不用手动操作DOM);② 组件化开发(页面拆成可复用的独立组件,提升效率);③ 双向数据绑定(v-model简化表单交互);④ 虚拟DOM(减少真实DOM操作,提性能);⑤ 指令系统(v-if、v-for等简化DOM操作逻辑)。

怎么理解Vue是"渐进式框架"?

答:渐进式是指Vue核心功能轻量,能根据需求逐步加扩展功能,不用一次性全引入。比如基础开发只用核心的数据绑定、组件;需要路由加vue-router;需要状态管理加Vuex/Pinia;需要工程化加Webpack/Vite。适配从小脚本到大型应用的不同场景,学习成本也能逐步提升。

Vue实例的生命周期钩子和普通方法有啥本质区别?

答:① 触发时机:钩子由Vue在实例特定阶段自动调(比如created在实例创建后),普通方法要手动调(比如点击事件触发);② 执行环境:钩子内this指向Vue实例,不用手动绑定;③ 用途:钩子用于初始化、请求数据、DOM操作等生命周期节点,普通方法处理业务逻辑。

Vue3的生命周期钩子和Vue2有哪些区别?

答:① 命名:组合式API里钩子加"on"(created→onCreated),选项式API名称不变;② 新增:onRenderTracked(追踪渲染依赖)、onRenderTriggered(触发渲染时调),用于调试;③ 销毁钩子:beforeDestroy/destroyed改成beforeUnmount/unmounted(语义更准);④ 执行:组合式API的钩子写在setup里,无需this访问实例。

Vue Router的核心作用是什么?有哪些常用路由模式?区别是什么?

答: ① 核心:实现SPA路由跳转,URL变不刷新页面,切换组件视图; ② 模式: hash模式(基于URL#,兼容好,URL带#) history模式(基于History API,URL无#,需后端配置,否则刷新404)。

自定义指令

自定义指令通过使用下列钩子来创建,以对齐元素的生命周期,它们都是可选的:

bind - 指令绑定到元素后调用。只调用一次。 inserted - 元素插入父 DOM 后调用。 update - 当元素更新,但子元素尚未更新时,将调用此钩子。 componentUpdated - 一旦组件和子级被更新,就会调用这个钩子。 unbind - 一旦指令被移除,就会调用这个钩子。也只调用一次

js 复制代码
Vue.directive('highlight', {
  bind(el, binding, vnode) {
    el.style.background = binding.value;
  },
});
相关推荐
程序员黑豆1 小时前
鸿蒙应用开发之父子组件传参:@Param、@Event、@Once 装饰器详解与实战
前端·harmonyos
ClouGence1 小时前
一个人录好的测试用例,团队怎么一起用?
前端·测试
无限压榨切图仔2 小时前
从 Claude Code 切到 Codex:我用 Agent、Skills、MCP 做完了一个内容运营工具
前端·后端
濮水大叔2 小时前
NestJS 与 CabloyJS 的 env/config 架构对比:从环境变量到实例级配置
前端·node.js·nestjs
成都渲染101云渲染66662 小时前
Blender渲染时,纯CPU渲染的设置教程
前端·javascript·blender
董员外2 小时前
RAG 系统进化论(一):纵览 RAG 的发展历程
前端·人工智能·后端
Gauss松鼠会2 小时前
【GaussDB】GaussDB锁阻塞源头查询
java·开发语言·前端·数据库·算法·gaussdb·经验总结
YHHLAI3 小时前
Vue 3 流式输出实战:从零掌握 LLM Streaming 与 SSE 协议
前端·javascript·vue.js
2601_965798473 小时前
Arrow Unlocker HTML5 Game Review: Keep Web Arcade Players Coming Back
前端·html·html5