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 包裹)

深度响应式可能影响性能(可用 shallowReactive 或 markRaw 优化)

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;
  },
});
相关推荐
卸任3 小时前
Vibe coding工具使用心得
前端·ai编程
brien94 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance4 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M4 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写4 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李4 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易4 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马5 小时前
前沿视界
前端
kyriewen5 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员
陈随易5 小时前
3000 万人在用的翻译插件,重写一遍就是一门生意
前端·后端·程序员