当前位置: 首页 > news >正文

Vue3 面试题及详细答案120道(61-75 )

前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,MySQL,Linux… 。

前后端面试题-专栏总目录

在这里插入图片描述

文章目录

  • 一、本文面试题目录
      • 61. Vue3 中如何实现组件的异步加载?
      • 62. 什么是 Vue3 的组合式 API 中的“依赖收集”?
      • 63. Vue3 中如何使用 Teleport 组件?
      • 64. Vue3 与 Vue2 的生命周期钩子有哪些区别?
      • 65. Vue3 中 `v-model` 的实现原理是什么?
      • 66. Vue3 中的 `ref` 和 `reactive` 有什么性能差异?
      • 67. 如何在 Vue3 中实现全局状态管理(不使用 Vuex/Pinia)?
      • 68. Vue3 中 `watch` 和 `watchEffect` 的区别是什么?
      • 69. Vue3 中如何处理组件的错误边界?
      • 70. 什么是 Vue3 的“渲染函数”?如何使用?
      • 71. Vue3 中如何实现跨组件通信?
      • 72. Vue3 中的 `defineProps` 和 `defineEmits` 有什么作用?
      • 73. Vue3 中如何优化长列表渲染性能?
      • 74. 什么是 Vue3 的“编译器宏”?有哪些常用宏?
      • 75. Vue3 中如何实现路由守卫?

一、本文面试题目录

61. Vue3 中如何实现组件的异步加载?

在 Vue3 中,可通过 defineAsyncComponent 函数实现组件的异步加载,它能将组件加载推迟到需要时进行,提升初始加载速度。

  • 基本用法:
    import { defineAsyncComponent } from 'vue'
    // 异步加载组件
    const AsyncComponent = defineAsyncComponent(() => import('./AsyncComponent.vue'))
    
  • 高级配置(可指定加载状态、错误处理等):
    const AsyncComponent = defineAsyncComponent({loader: () => import('./AsyncComponent.vue'),loadingComponent: LoadingComponent, // 加载中显示的组件errorComponent: ErrorComponent, // 加载失败显示的组件delay: 200, // 延迟多久后显示加载组件(默认 200ms)timeout: 3000 // 超时时间,超过则显示错误组件
    })
    

62. 什么是 Vue3 的组合式 API 中的“依赖收集”?

依赖收集是 Vue3 响应式系统的核心机制,指追踪组件渲染过程中使用的响应式数据,当这些数据变化时,自动触发相关组件或副作用的重新执行。

  • 实现原理:
    1. 执行副作用函数(如组件渲染函数、watch 回调)时,Vue 会将当前副作用函数设为“活跃状态”。
    2. 访问响应式数据时,数据的 getter 会将活跃副作用函数添加到自身的依赖列表中。
    3. 当数据变化触发 setter 时,会遍历依赖列表,执行所有关联的副作用函数。

63. Vue3 中如何使用 Teleport 组件?

Teleport( teleport 译为“传送”)用于将组件的 DOM 结构“传送”到页面的指定位置,解决嵌套组件样式或层级冲突问题(如模态框、弹窗)。

  • 基本用法:
    <template><button @click="showModal = true">打开弹窗</button><Teleport to="body"> <!-- 将内容传送到 body 标签下 --><div v-if="showModal" class="modal"><p>这是弹窗内容</p><button @click="showModal = false">关闭</button></div></Teleport>
    </template>
    <script setup>
    import { ref } from 'vue'
    const showModal = ref(false)
    </script>
    
  • 注意:to 属性值可以是 CSS 选择器或 DOM 元素,且传送的内容仍受当前组件的响应式数据控制。

64. Vue3 与 Vue2 的生命周期钩子有哪些区别?

Vue3 保留了大部分 Vue2 的生命周期概念,但在组合式 API 中采用函数式写法,且部分钩子名称有调整:

Vue2 选项式 APIVue3 组合式 API说明
beforeCreate无(可在 setup 中替代)初始化前,setup 执行时机类似
created无(可在 setup 中替代)初始化后,setup 执行时机类似
beforeMountonBeforeMount挂载前触发
mountedonMounted挂载后触发
beforeUpdateonBeforeUpdate更新前触发
updatedonUpdated更新后触发
beforeDestroyonBeforeUnmount卸载前触发(名称调整)
destroyedonUnmounted卸载后触发(名称调整)
errorCapturedonErrorCaptured捕获子组件错误时触发
  • 新增钩子:onRenderTracked(渲染追踪时触发)、onRenderTriggered(渲染触发时触发),用于调试响应式依赖。

65. Vue3 中 v-model 的实现原理是什么?

Vue3 中 v-model 是语法糖,本质是通过props 和事件实现父子组件数据双向绑定,相比 Vue2 更灵活,支持自定义修饰符和多个 v-model

  • 基本原理:
    • 父组件使用 v-model:propName="value" 时,等价于 :propName="value" @update:propName="value = $event"
    • 子组件通过 defineProps 接收 propName,并通过 defineEmits 触发 update:propName 事件传递新值。
  • 示例:
    <!-- 父组件 -->
    <ChildComponent v-model:count="num" /><!-- 子组件 -->
    <template><button @click="handleClick">点击</button>
    </template>
    <script setup>
    const props = defineProps(['count'])
    const emit = defineEmits(['update:count'])
    const handleClick = () => {emit('update:count', props.count + 1) // 触发更新事件
    }
    </script>
    

66. Vue3 中的 refreactive 有什么性能差异?

refreactive 都是创建响应式数据的 API,但实现机制不同,性能表现有差异:

  • reactive
    • 基于 Proxy 实现,直接代理对象,对对象的属性访问/修改进行拦截。
    • 性能:对于大型对象,初始化时需要递归代理所有属性,可能有轻微性能损耗;但访问属性时无需额外解包,效率较高。
  • ref
    • 用于基本类型或单个值,内部通过 { value: ... } 包装,访问/修改需通过 .value
    • 性能:初始化轻量,但每次访问/修改都需经过 .value 的 getter/setter,频繁操作时可能比 reactive 略慢。
  • 建议:
    • 基本类型或单个值用 ref,对象/数组用 reactive
    • 频繁操作的响应式数据优先考虑 reactive(如复杂表单)。

67. 如何在 Vue3 中实现全局状态管理(不使用 Vuex/Pinia)?

可通过响应式数据 + 全局注入实现简单全局状态管理,适用于小型项目:

  1. 创建全局响应式数据:
    // store.js
    import { reactive, readonly } from 'vue'
    const state = reactive({userInfo: null,theme: 'light'
    })
    // 对外暴露只读版本,防止直接修改
    const globalState = readonly(state)
    // 定义修改状态的方法
    const mutations = {setUserInfo(info) {state.userInfo = info},toggleTheme() {state.theme = state.theme === 'light' ? 'dark' : 'light'}
    }
    export { globalState, mutations }
    
  2. 在组件中使用:
    <script setup>
    import { globalState, mutations } from './store.js'
    // 读取状态
    console.log(globalState.theme)
    // 修改状态
    mutations.setUserInfo({ name: 'Vue3' })
    </script>
    
  • 缺点:缺乏 Vuex/Pinia 的模块化、DevTools 追踪、中间件等功能,大型项目仍建议使用 Pinia。

68. Vue3 中 watchwatchEffect 的区别是什么?

watchwatchEffect 都是监听响应式数据变化的 API,但用法和场景不同:

特性watchwatchEffect
依赖指定需明确指定监听的数据源(如 watch(refA, ...)自动收集依赖(函数内使用的响应式数据均会被监听)
初始执行默认不执行,需通过 immediate: true 开启默认初始执行一次
回调参数可获取新旧值((newVal, oldVal) => {}无参数,仅执行副作用
适用场景需明确监听特定数据,或需要新旧值对比依赖不明确,或需要初始执行的副作用(如数据加载)
  • 示例:
    const count = ref(0)
    // watch:明确监听 count
    watch(count, (newVal, oldVal) => {console.log('count变化:', newVal, oldVal)
    })// watchEffect:自动监听内部使用的 count
    watchEffect(() => {console.log('count当前值:', count.value)
    })
    

69. Vue3 中如何处理组件的错误边界?

Vue3 中可通过 onErrorCaptured 钩子或自定义错误边界组件捕获子组件的错误,防止错误扩散导致整个应用崩溃:

  • 方法1:使用 onErrorCaptured 钩子(组件内局部捕获):
    <script setup>
    import { onErrorCaptured, ref } from 'vue'
    const hasError = ref(false)onErrorCaptured((err, instance, info) => {console.error('捕获到错误:', err, info)hasError.value = truereturn true // 阻止错误继续向上传播
    })
    </script>
    
  • 方法2:自定义错误边界组件(全局复用):
    <!-- ErrorBoundary.vue -->
    <template><slot v-if="!hasError" /><div v-else>发生错误:{{ error.message }}</div>
    </template>
    <script setup>
    import { ref, onErrorCaptured } from 'vue'
    const hasError = ref(false)
    const error = ref(null)onErrorCaptured((err) => {hasError.value = trueerror.value = errreturn true
    })
    </script>
    
  • 使用错误边界组件:
    <ErrorBoundary><ChildComponent /> <!-- 子组件的错误会被捕获 -->
    </ErrorBoundary>
    

70. 什么是 Vue3 的“渲染函数”?如何使用?

渲染函数是用 JavaScript 代码描述组件渲染内容的函数,相比模板更灵活,适用于动态生成复杂 DOM 结构的场景。Vue3 中通过 h 函数(createVNode 的别名)创建虚拟 DOM 节点。

  • 基本用法:
    <script setup>
    import { h } from 'vue'// 定义渲染函数组件
    const MyComponent = (props) => {return h('div', { class: 'my-component' }, [h('h1', `Hello ${props.name}`),h('p', '这是渲染函数生成的内容')])
    }MyComponent.props = ['name'] // 声明 props
    </script><template><MyComponent name="Vue3" />
    </template>
    
  • 与模板的关系:模板最终会被编译为渲染函数,渲染函数是 Vue 内部渲染的底层实现。

No.大剑师精品GIS教程推荐
0地图渲染基础- 【WebGL 教程】 - 【Canvas 教程】 - 【SVG 教程】
1Openlayers 【入门教程】 - 【源代码+示例 300+】
2Leaflet 【入门教程】 - 【源代码+图文示例 150+】
3MapboxGL【入门教程】 - 【源代码+图文示例150+】
4Cesium 【入门教程】 - 【源代码+综合教程 200+】
5threejs【中文API】 - 【源代码+图文示例200+】

71. Vue3 中如何实现跨组件通信?

Vue3 提供多种跨组件通信方式,适用于不同场景:

  1. Props / Emits:父子组件通信,父传子用 props,子传父用 emits
  2. Provide / Inject:祖孙组件通信,祖先通过 provide 提供数据,后代通过 inject 接收。
    // 祖先组件
    import { provide } from 'vue'
    provide('theme', 'dark')// 后代组件
    import { inject } from 'vue'
    const theme = inject('theme', 'light') // 第二个参数为默认值
    
  3. 全局状态管理:如 Pinia、Vuex,适用于任意组件间共享状态。
  4. 事件总线(Event Bus):通过 mitt 库实现(Vue3 移除了内置 $on/$emit):
    // bus.js
    import mitt from 'mitt'
    export const bus = mitt()// 组件A发送事件
    bus.emit('user-updated', userInfo)// 组件B接收事件
    bus.on('user-updated', (info) => { ... })
    

72. Vue3 中的 definePropsdefineEmits 有什么作用?

definePropsdefineEmits 是 Vue3 <script setup> 语法中用于声明组件 props 和自定义事件的编译宏,无需导入即可使用:

  • defineProps:声明组件接收的 props,支持类型校验和默认值。
    // 基础用法
    const props = defineProps(['name', 'age'])// 带类型和默认值
    const props = defineProps({name: { type: String, required: true },age: { type: Number, default: 18 }
    })
    
  • defineEmits:声明组件可触发的自定义事件,支持类型校验。
    // 基础用法
    const emit = defineEmits(['change', 'submit'])// 带类型校验
    const emit = defineEmits({change: (value) => typeof value === 'string', // 验证事件参数submit: () => true // 无需参数
    })// 触发事件
    emit('change', 'new value')
    
  • 特点:在 <script setup> 中自动具备类型推断,且返回的 props 是响应式的(只读),emit 是触发事件的函数。

73. Vue3 中如何优化长列表渲染性能?

长列表(如 1000+ 条数据)渲染可能导致性能问题,可通过以下方式优化:

  1. 虚拟滚动:只渲染可视区域内的列表项,通过 vue-virtual-scroller 等库实现。
    <template><RecycleScroller:items="longList":item-size="50"class="scroller"><template v-slot="{ item }"><div class="list-item">{{ item.text }}</div></template></RecycleScroller>
    </template>
    
  2. 懒加载:监听滚动事件,当列表滚动到一定位置时再加载更多数据。
  3. 避免响应式数据冗余:长列表数据若无需响应式,可使用 markRaw 标记为非响应式。
    import { markRaw } from 'vue'
    const longList = markRaw([/* 大量数据 */]) // 关闭响应式
    
  4. 使用 v-memo:缓存列表项,仅当依赖变化时重新渲染。
    <div v-for="item in list" :key="item.id" v-memo="[item.id, item.name]">{{ item.name }}
    </div>
    

74. 什么是 Vue3 的“编译器宏”?有哪些常用宏?

编译器宏是 Vue3 中仅在 <script setup>setup() 函数中生效的特殊函数,由 Vue 编译器处理,无需导入即可使用,用于简化组件逻辑:

  • 常用编译器宏:
    1. defineProps:声明组件 props。
    2. defineEmits:声明组件自定义事件。
    3. defineExpose:暴露组件内部属性/方法,供父组件通过 ref 访问。
      const count = ref(0)
      const increment = () => count.value++
      defineExpose({ count, increment }) // 父组件可通过 ref 访问
      
    4. withDefaults:为 defineProps 提供更灵活的默认值配置(支持函数返回默认值)。
      const props = withDefaults(defineProps({list: { type: Array },config: { type: Object }
      }), {list: () => [], // 函数返回默认值(避免复用同一引用)config: () => ({ theme: 'light' })
      })
      

75. Vue3 中如何实现路由守卫?

Vue3 中路由守卫的用法与 Vue2 类似,但需结合 Vue Router 4+ 的 API,常用守卫包括:

  1. 全局守卫
    // router/index.js
    import { createRouter } from 'vue-router'
    const router = createRouter(/* 配置 */)// 全局前置守卫(跳转前触发)
    router.beforeEach((to, from, next) => {if (to.meta.requiresAuth && !isLogin) {next('/login') // 未登录则跳转到登录页} else {next() // 允许跳转}
    })// 全局后置守卫(跳转后触发)
    router.afterEach((to, from) => {document.title = to.meta.title || '默认标题'
    })
    
  2. 路由独享守卫(在路由配置中定义):
    const routes = [{path: '/admin',component: Admin,beforeEnter: (to, from, next) => { // 仅当前路由生效if (!isAdmin) next('/forbidden')else next()}}
    ]
    
  3. 组件内守卫
    <script setup>
    import { onBeforeRouteEnter, onBeforeRouteLeave } from 'vue-router'// 进入组件前触发(此时组件实例未创建,无法访问 this)
    onBeforeRouteEnter((to, from, next) => {next(vm => { // 通过 vm 访问组件实例vm.fetchData()})
    })// 离开组件前触发
    onBeforeRouteLeave((to, from, next) => {if (confirm('确定离开吗?')) next()else next(false) // 取消跳转
    })
    </script>
    
http://www.lryc.cn/news/596808.html

相关文章:

  • Python学习:函数的使用
  • webrtc整体架构
  • LeetCode热题100--205
  • Visual Studio中部署PaddleOCRv5 (借助ncnn框架)
  • Flink 状态管理设计详解:StateBackend、State、RocksDB和Namespace
  • 【笔记】Handy Multi-Agent Tutorial 第三章: CAMEL框架简介及实践(实践部分)
  • Redis原理之分布式锁
  • PowerShell自动化核对AD与HR系统账户信息实战指南
  • IDEA202403 超好用设置【持续更新】
  • ZooKeeper在Hadoop中的协同应用:从NameNode选主到分布式锁实现
  • 天津大学陈亚楠教授团队 ACS AEM:焦耳热超快合成非平衡态能源材料——毫秒级制备与跨体系性能突破
  • 昨天去看了电科金仓的发布会,有点东西!
  • 从 Linux 将文件下载到 Windows 的几种实用方法
  • 【AI智能体】Dify 开发与集成MCP服务实战操作详解
  • 嵌入式学习之路
  • Python笔记之跨文件实例化、跨文件调用、导入库
  • 为什么本地ip记录成0.0.0.1
  • 基于Python flask的常用AI工具功能数据分析与可视化系统设计与实现,技术包括LSTM、SVM、朴素贝叶斯三种算法,echart可视化
  • 慢 SQL接口性能优化实战
  • Fast Frequency Estimation Algorithm by Least Squares Phase Unwrapping
  • USB4.0:开启高速数据传输的新时代
  • 当if else比较多时候应该怎么避免?
  • MCP与企业数据集成:ERP、CRM、数据仓库的统一接入
  • #Linux权限管理:从“Permission denied“到系统安全大师
  • uniapp自定义圆形勾选框和全选框
  • iOS 抓包工具有哪些?2025实用指南与场景推荐
  • 重磅发布:Oracle ADG 一键自动化搭建脚本
  • 离线快速处理PDF格式转化的方案
  • 揭秘ThreadLocal核心原理与应用
  • Linux文件系统理解1