文章目录
-
- [一、Vue2 核心原理与实战](#一、Vue2 核心原理与实战)
-
- [1. 问题:Vue2 响应式原理的实现细节及缺陷?](#1. 问题:Vue2 响应式原理的实现细节及缺陷?)
- [2. 问题:Vue2 中`nextTick\`的原理与使用场景?](#2. 问题:Vue2 中`nextTick`的原理与使用场景?)
- [3. 问题:Vue2 组件通信的 7 种方式及适用场景?](#3. 问题:Vue2 组件通信的 7 种方式及适用场景?)
- [4. 问题:Vue2 中 Vuex 的模块化实现及命名空间用法?](#4. 问题:Vue2 中 Vuex 的模块化实现及命名空间用法?)
- [5. 问题:Vue2 的生命周期钩子及父子组件执行顺序?](#5. 问题:Vue2 的生命周期钩子及父子组件执行顺序?)
- [二、Vue3 核心特性与进阶](#二、Vue3 核心特性与进阶)
-
- [1. 问题:Vue3 响应式原理与 Vue2 的本质区别?(2025 高频)](#1. 问题:Vue3 响应式原理与 Vue2 的本质区别?(2025 高频))
- [2. 问题:Vue3 中 Ref 与 Reactive 的区别及最佳实践?](#2. 问题:Vue3 中 Ref 与 Reactive 的区别及最佳实践?)
- [3. 问题:Vue3 Composition API 与 Options API 的区别?为何推荐 Composition API?](#3. 问题:Vue3 Composition API 与 Options API 的区别?为何推荐 Composition API?)
- [4. 问题:Vue3 `script setup`语法糖的核心特性?](#4. 问题:Vue3
script setup
语法糖的核心特性?) - [5. 问题:Vue3 中 Teleport(瞬移)组件的用途及实现?](#5. 问题:Vue3 中 Teleport(瞬移)组件的用途及实现?)
- [6. 问题:Vue3 中 Pinia 与 Vuex 的区别?为何 Pinia 成为 2025 主流?](#6. 问题:Vue3 中 Pinia 与 Vuex 的区别?为何 Pinia 成为 2025 主流?)
- [三、Vue 生态工具与 2025 新趋势](#三、Vue 生态工具与 2025 新趋势)
-
- [1. 问题:2025 年 Vue 项目为何开始用 Alova 替代 Axios?(最新考点)](#1. 问题:2025 年 Vue 项目为何开始用 Alova 替代 Axios?(最新考点))
- [2. 问题:Vue3 中 Vite 相比 Webpack 的核心优势?2025 配置最佳实践?](#2. 问题:Vue3 中 Vite 相比 Webpack 的核心优势?2025 配置最佳实践?)
- [3. 问题:Element Plus 在 2025 年的核心更新及实战优化?](#3. 问题:Element Plus 在 2025 年的核心更新及实战优化?)
- [4. 问题:Vue3 中如何实现组件的按需引入与 Tree Shaking?](#4. 问题:Vue3 中如何实现组件的按需引入与 Tree Shaking?)
- [5. 问题:Vue3 项目的 TypeScript 最佳实践?2025 类型定义技巧?](#5. 问题:Vue3 项目的 TypeScript 最佳实践?2025 类型定义技巧?)
- [四、Vue2 迁移 Vue3 实战问题](#四、Vue2 迁移 Vue3 实战问题)
-
- [1. 问题:Vue2 项目迁移 Vue3 的核心步骤及 2025 工具推荐?](#1. 问题:Vue2 项目迁移 Vue3 的核心步骤及 2025 工具推荐?)
- [2. 问题:Vue2 迁移 Vue3 后常见的兼容性问题及解决方案?](#2. 问题:Vue2 迁移 Vue3 后常见的兼容性问题及解决方案?)
- [3. 问题:Vue2 到 Vue3 的响应式数据迁移技巧?](#3. 问题:Vue2 到 Vue3 的响应式数据迁移技巧?)
- [4. 问题:Vue2 项目迁移后如何优化性能?2025 实战方案?](#4. 问题:Vue2 项目迁移后如何优化性能?2025 实战方案?)
- [5. 问题:Vue3 迁移后的测试策略?2025 主流测试工具?](#5. 问题:Vue3 迁移后的测试策略?2025 主流测试工具?)
- 总结
一、Vue2 核心原理与实战
1. 问题:Vue2 响应式原理的实现细节及缺陷?
答案 :基于Object.defineProperty()
劫持对象属性的getter/setter
,结合依赖收集(Dep)和观察者(Watcher)实现响应式。
-
实现流程:初始化时遍历 data,为每个属性定义
getter
(收集依赖到 Dep)和setter
(触发 Dep 中 Watcher 更新); -
核心缺陷:
-
对象新增 / 删除属性无法监听(需
this.$set(obj, key, val)
); -
数组下标修改(
this.arr[0] = 1
)和长度变化(this.arr.length = 0
)无响应; -
初始化时递归劫持所有属性,大型对象性能开销高。
2. 问题:Vue2 中$nextTick
的原理与使用场景?
答案:基于 JavaScript 事件循环(Event Loop)实现,将回调延迟到 DOM 更新完成后执行。
-
原理:优先使用
Promise.then
,其次MutationObserver
,最后setTimeout
降级,确保回调在当前 tick 的 DOM 更新后触发; -
场景:操作 DOM 后获取更新后的属性(如获取 v-if 切换后的元素高度);
-
代码示例:
javascript
<template>
<div ref="box" v-if="show">{{ content }}</div>
<button @click="toggle">显示并获取高度</button>
</template>
<script>
export default {
data() { return { show: false, content: '测试' } },
methods: {
toggle() {
this.show = true;
// 直接获取为0,需用$nextTick
this.$nextTick(() => {
console.log(this.$refs.box.offsetHeight); // 正确获取高度
});
}
}
};
</script>
3. 问题:Vue2 组件通信的 7 种方式及适用场景?
答案:
-
父→子:Props(基础数据传递);
-
子→父:
$emit
+ 自定义事件(简单数据回传); -
兄弟组件:
$parent
/$children
(层级浅)、Vuex(复杂状态); -
跨层级:
provide/inject
(祖先向后代注入依赖)、$attrs/$listeners
(透传属性 / 事件); -
任意组件:Vuex(全局状态)、事件总线(
new Vue()
实例,适用于小型项目);
- 代码示例(事件总线):
javascript
// main.js 注册总线
Vue.prototype.$bus = new Vue();
// 组件A发送
this.$bus.$emit('msg', 'Hello');
// 组件B接收
mounted() {
this.$bus.$on('msg', (data) => console.log(data));
},
beforeDestroy() {
this.$bus.$off('msg'); // 销毁时解绑
}
4. 问题:Vue2 中 Vuex 的模块化实现及命名空间用法?
答案 :当状态过多时,拆分modules
实现模块化,通过namespaced: true
开启命名空间避免冲突。
- 核心配置:
javascript
// store/modules/user.js
export default {
namespaced: true, // 开启命名空间
state: { name: '张三', role: 'user' },
mutations: {
updateName(state, payload) {
state.name = payload;
}
},
actions: {
fetchUser({ commit }) {
// 模拟接口请求
setTimeout(() => commit('updateName', '李四'), 1000);
}
}
};
// store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import user from './modules/user';
Vue.use(Vuex);
export default new Vuex.Store({ modules: { user } });
- 组件中使用:
javascript
<script>
import { mapState, mapActions } from 'vuex';
export default {
computed: {
...mapState('user', ['name']) // 指定模块名
},
methods: {
...mapActions('user', ['fetchUser'])
}
};
</script>
5. 问题:Vue2 的生命周期钩子及父子组件执行顺序?
答案 :8 个核心钩子按顺序执行:beforeCreate
→created
→beforeMount
→mounted
→beforeUpdate
→updated
→beforeDestroy
→destroyed
;
-
父子执行顺序:
挂载阶段:父
beforeCreate
→父created
→父beforeMount
→子beforeCreate
→子created
→子beforeMount
→子mounted
→父mounted
;销毁阶段:父
beforeDestroy
→子beforeDestroy
→子destroyed
→父destroyed
; -
关键钩子作用:
created
(获取数据,未挂载 DOM)、mounted
(操作 DOM)、destroyed
(解绑事件 / 清除定时器)。
二、Vue3 核心特性与进阶
1. 问题:Vue3 响应式原理与 Vue2 的本质区别?(2025 高频)
答案 :核心差异在于响应式实现方式,Vue3 基于Proxy
替代Object.defineProperty
,配合Reflect
实现更完善的响应式。
- 关键优势:
-
支持对象新增 / 删除属性(无需
$set
); -
支持数组下标修改和长度变化(
arr[0] = 1
有效); -
惰性监听(仅访问属性时才劫持,优化大型对象性能);
-
可监听 Map、Set 等复杂数据类型;
- Reactive 核心代码示例:
javascript
<script setup>
import { reactive } from 'vue';
const user = reactive({ name: '张三', hobbies: ['篮球'] });
// 支持新增属性
user.age = 20;
// 支持数组下标修改
user.hobbies[0] = '足球';
console.log(user.hobbies); // 响应式更新为['足球']
</script>
2. 问题:Vue3 中 Ref 与 Reactive 的区别及最佳实践?
答案:两者均用于创建响应式数据,适用场景不同:
特性 | Ref | Reactive |
---|---|---|
适用类型 | 基本类型、对象 / 数组 | 仅对象 / 数组 |
访问方式 | 需.value (模板自动解包) |
直接访问属性 |
重新赋值 | 支持(ref.value = 新值 ) |
不支持(需修改属性) |
-
最佳实践:
-
基本类型(Number、String)优先用 Ref;
-
复杂对象(如用户信息、表单数据)用 Reactive;
-
解构 Reactive 对象需用
toRefs
保持响应式:
-
javascript
<script setup>
import { reactive, toRefs } from 'vue';
const user = reactive({ name: '张三', age: 20 });
const { name, age } = toRefs(user); // 解构后仍为响应式
age.value++; // 触发更新
</script>
3. 问题:Vue3 Composition API 与 Options API 的区别?为何推荐 Composition API?
答案:Composition API 是 Vue3 的核心语法升级,按逻辑关注点组织代码,替代 Options API 的按选项(data、methods)组织。
- 核心优势:
-
逻辑复用更灵活(无需 mixins,避免命名冲突);
-
大型组件代码更易维护(相关逻辑聚合成 "组合函数");
-
类型支持更友好(适配 TypeScript);
- 组合函数示例(封装用户数据逻辑):
javascript
// composables/useUser.js(组合函数)
import { reactive, onMounted } from 'vue';
export function useUser() {
const user = reactive({ name: '', age: 0 });
// 加载用户数据逻辑
const fetchUser = () => {
// 模拟接口请求
setTimeout(() => {
user.name = '张三';
user.age = 20;
}, 1000);
};
onMounted(fetchUser);
return { user, fetchUser };
}
// 组件中使用
<script setup>
import { useUser } from '@/composables/useUser';
const { user, fetchUser } = useUser(); // 复用逻辑
</script>
4. 问题:Vue3 script setup
语法糖的核心特性?
答案 :script setup
是 Vue3 推荐的组件写法,简化 Composition API 代码,核心特性:
-
自动注册组件(无需
components
选项); -
直接声明 Props(
defineProps
)和事件(defineEmits
); -
支持顶层 await(无需包裹在 async 函数中);
-
暴露变量 / 函数到模板(无需 return);
- 完整示例:
javascript
<template>
<div>{{ title }}:{{ count }}</div>
<button @click="handleClick">+1</button>
<Child :msg="user.name" />
</template>
<script setup>
// 1. 导入组件(自动注册)
import Child from './Child.vue';
import { ref, defineProps, defineEmits } from 'vue';
// 2. 定义Props
const props = defineProps({
title: { type: String, required: true }
});
// 3. 定义事件
const emit = defineEmits(['count-change']);
// 4. 响应式数据(直接暴露到模板)
const count = ref(0);
const user = await fetch('/api/user').then(res => res.json()); // 顶层await
// 5. 方法(直接暴露到模板)
const handleClick = () => {
count.value++;
emit('count-change', count.value); // 触发事件
};
</script>
5. 问题:Vue3 中 Teleport(瞬移)组件的用途及实现?
答案:Teleport 用于将组件内容渲染到 DOM 树的指定位置,解决模态框、弹窗等组件的样式隔离问题。
-
核心场景:弹窗组件渲染到
body
下,避免父组件overflow: hidden
或z-index
冲突; -
代码示例:
javascript
<!-- components/Modal.vue -->
<template>
<teleport to="body"> <!-- 渲染到body下 -->
<div class="modal-mask">
<div class="modal-content">
<slot></slot>
<button @click="close">关闭</button>
</div>
</div>
</teleport>
</template>
<script setup>
const emit = defineEmits(['close']);
const close = () => emit('close');
</script>
<style scoped>
.modal-mask {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0,0,0,0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999; /* 避免被父组件遮挡 */
}
</style>
6. 问题:Vue3 中 Pinia 与 Vuex 的区别?为何 Pinia 成为 2025 主流?
答案:Pinia 是 Vue3 官方推荐的状态管理库,替代 Vuex,核心差异:
特性 | Vuex | Pinia |
---|---|---|
模块化 | 需modules + 命名空间 |
每个 store 即模块 |
状态修改 | 需通过mutations (同步) |
直接修改状态(支持同步 / 异步) |
TypeScript 支持 | 需手动类型声明 | 天生支持,类型自动推导 |
开发工具 | 仅支持 Vue2 DevTools | 支持 Vue3 DevTools |
- Pinia 基础用法:
javascript
// stores/user.js
import { defineStore } from 'pinia';
import { ref } from 'vue';
// 定义store(自动成为模块)
export const useUserStore = defineStore('user', () => {
// 状态(类似Vuex的state)
const name = ref('张三');
const age = ref(20);
// 计算属性(类似getters)
const isAdult = computed(() => age.value >= 18);
// 动作(类似actions,支持异步)
const fetchUser = async () => {
const res = await fetch('/api/user');
const data = await res.json();
name.value = data.name;
age.value = data.age;
};
return { name, age, isAdult, fetchUser };
});
// 组件中使用
<script setup>
import { useUserStore } from '@/stores/user';
const userStore = useUserStore();
userStore.fetchUser(); // 调用异步动作
</script>
三、Vue 生态工具与 2025 新趋势
1. 问题:2025 年 Vue 项目为何开始用 Alova 替代 Axios?(最新考点)
答案:Alova 是 2025 年前端主流请求库,针对 Vue 等框架优化,相比 Axios 有明显优势:
- 核心优势:
-
极致轻量:基础包仅 4KB(Axios 12KB),支持 Tree-shaking;
-
智能请求管理:内置请求竞态取消、重复请求合并、错误重试;
-
声明式 API:与 Vue3 Composition API 深度集成,自动管理 loading/error 状态;
-
中间件机制:替代 Axios 拦截器,逻辑更清晰;
- Vue3 中使用 Alova 示例:
javascript
<script setup>
import { createAlova, useRequest } from 'alova';
import { vueHook } from '@alova/vue';
// 1. 创建Alova实例(全局配置)
const alova = createAlova({
baseURL: 'https://api.example.com',
statesHook: vueHook, // 适配Vue3
// 中间件替代Axios拦截器
beforeRequest: (method) => {
method.config.headers.token = localStorage.getItem('token');
},
responded: (response) => response.json() // 自动解析JSON
});
// 2. 定义API
const userAPI = {
getDetail: (id) => alova.Get(`/user/${id}`)
};
// 3. 声明式请求(自动管理loading/error)
const { data: user, loading, error } = useRequest(userAPI.getDetail(1), {
retry: 3, // 错误重试3次
dedupe: true // 合并重复请求
});
</script>
<template>
<div v-if="loading">加载中...</div>
<div v-if="error">请求失败:{{ error.message }}</div>
<div v-if="user">姓名:{{ user.name }}</div>
</template>
2. 问题:Vue3 中 Vite 相比 Webpack 的核心优势?2025 配置最佳实践?
答案:Vite 已成为 2025 年 Vue 项目默认构建工具,优势源于 "按需编译" 而非 "打包后启动":
- 核心优势:
-
开发启动快(毫秒级):无需打包,直接请求源码;
-
热更新快:仅编译修改的模块;
-
配置简单:内置 Vue3 支持,无需复杂 loader 配置;
- 2025 最佳配置(vite.config.js):
javascript
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';
export default defineConfig({
plugins: [vue()],
// 路径别名
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
},
// 开发服务器配置
server: {
port: 3000,
open: true,
proxy: {
'/api': {
target: 'https://api.example.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^/api/, '')
}
}
},
// 构建优化
build: {
target: 'es2015', // 适配现代浏览器
rollupOptions: {
output: {
// 拆分chunk,优化缓存
manualChunks: {
vue: ['vue', 'vue-router', 'pinia'],
alova: ['alova', '@alova/vue']
}
}
}
}
});
3. 问题:Element Plus 在 2025 年的核心更新及实战优化?
答案:Element Plus 作为 Vue3 主流 UI 库,2025 年重点优化了性能和生态适配:
- 核心更新:
-
虚拟滚动表格(el-table-v2):支持 10 万条数据无卡顿;
-
SVG 图标替代字体图标:解决 "小方块" 乱码问题,减少体积;
-
深度支持 TypeScript:所有组件类型自动推导;
-
国际化优化:支持 52 种语言,新增动态切换 API;
- 虚拟滚动表格实战:
javascript
<template>
<!-- 10万条数据无卡顿 -->
<el-table-v2
:columns="columns"
:data="largeData"
:height="500"
/>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { ElTableV2 } from 'element-plus';
import 'element-plus/theme-chalk/el-table-v2.css';
// 定义列
const columns = [
{ key: 'name', title: '姓名', width: 120 },
{ key: 'age', title: '年龄', width: 80 },
{ key: 'address', title: '地址', width: 200 }
];
// 模拟10万条数据
const largeData = ref([]);
onMounted(() => {
largeData.value = Array.from({ length: 100000 }, (_, i) => ({
name: `用户${i}`,
age: 18 + Math.floor(Math.random() * 20),
address: `北京市朝阳区${i}号`
}));
});
</script>
4. 问题:Vue3 中如何实现组件的按需引入与 Tree Shaking?
答案:按需引入可减少打包体积,2025 年主流方案结合 Vite 和组件库自动导入:
- 核心实现:
-
UI 库按需引入:使用
unplugin-vue-components
自动导入 Element Plus 等组件; -
工具函数按需引入:使用 ES Module 语法(
import { ref } from 'vue'
),Vite 自动 Tree Shaking;
- 配置示例(自动导入组件):
javascript
// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
export default defineConfig({
plugins: [
vue(),
// 自动导入Element Plus组件
Components({
resolvers: [ElementPlusResolver()],
dts: true // 生成类型声明文件
})
]
});
- 组件中直接使用(无需 import):
javascript
<template>
<!-- 自动导入ElButton,无需import -->
<el-button type="primary">按钮</el-button>
</template>
5. 问题:Vue3 项目的 TypeScript 最佳实践?2025 类型定义技巧?
答案:Vue3 天生支持 TypeScript,2025 年重点关注类型复用和自动推导:
- 核心技巧:
-
用
interface
定义对象类型,type
定义联合 / 交叉类型; -
组件 Props 用
defineProps
自动推导类型; -
响应式数据用
ref<T>
/reactive<T>
指定泛型; -
组合函数返回类型自动推导,无需手动声明;
- 实战示例:
javascript
<script setup lang="ts">
import { ref, reactive, defineProps } from 'vue';
// 1. 定义接口类型
interface User {
id: number;
name: string;
age?: number; // 可选属性
}
// 2. Props类型自动推导
const props = defineProps<{
title: string;
user: User; // 使用自定义接口
}>();
// 3. 响应式数据指定泛型
const count = ref<number>(0);
const userList = reactive<User[]>([]);
// 4. 函数返回类型自动推导
const fetchUser = async (id: number): Promise<User> => {
const res = await fetch(`/api/user/${id}`);
return res.json();
};
// 5. 调用函数(类型自动校验)
fetchUser(1).then(user => {
userList.push(user);
});
</script>
四、Vue2 迁移 Vue3 实战问题
1. 问题:Vue2 项目迁移 Vue3 的核心步骤及 2025 工具推荐?
答案:2025 年迁移工具更成熟,推荐 "渐进式迁移" 方案,核心步骤:
-
环境升级:Node.js ≥ 14.18,npm ≥ 6.14;
-
依赖替换:
vue@2
→vue@3
,vue-router@3
→vue-router@4
,vuex
→pinia
; -
代码改造:
-
Options API→Composition API(优先用
script setup
); -
Vue.prototype
→app.config.globalProperties
; -
过滤器(filter)→计算属性或函数;
- 工具辅助:使用
vue-codemod
自动转换代码,vue-devtools
调试;
- 全局属性注册示例:
javascript
// Vue2
Vue.prototype.$http = axios;
// Vue3(main.js)
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
app.config.globalProperties.$http = axios;
app.mount('#app');
// 组件中使用(需用getCurrentInstance)
<script setup>
import { getCurrentInstance } from 'vue';
const { proxy } = getCurrentInstance();
proxy.$http.get('/api/user');
</script>
2. 问题:Vue2 迁移 Vue3 后常见的兼容性问题及解决方案?
答案:2025 年仍有部分老项目迁移,常见问题及解决:
-
问题:
this
指向丢失(script setup
无this
);解决:用
getCurrentInstance
获取组件实例,或直接使用组合 API; -
问题:路由
mode: 'history'
配置变化;解决:Vue Router 4 用
createWebHistory
替代:
javascript
// Vue2
const router = new VueRouter({ mode: 'history', routes });
// Vue3
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({ history: createWebHistory(), routes });
-
问题:Vuex 状态无法访问;
解决:迁移到 Pinia,或使用
vuex@4
适配 Vue3; -
问题:第三方组件库不兼容;
解决:升级组件库到 Vue3 版本(如 Element UI→Element Plus)。
3. 问题:Vue2 到 Vue3 的响应式数据迁移技巧?
答案:响应式实现变化导致数据处理方式不同,迁移技巧:
-
对象数据:Vue2 的
data()
对象→Vue3 的reactive
; -
基本类型:Vue2 的
data()
基本类型→Vue3 的ref
; -
数组数据:Vue2 的
$set
/ 变异方法→Vue3 直接修改; -
复杂数据:Vue2 的
Vue.observable
→Vue3 的reactive
;
- 迁移对比示例:
javascript
// Vue2
export default {
data() {
return {
user: { name: '张三' }, // 对象
count: 0, // 基本类型
list: [1, 2, 3] // 数组
};
},
methods: {
updateData() {
this.$set(this.user, 'age', 20); // 新增属性
this.count++;
this.list.push(4); // 变异方法
}
}
};
// Vue3(script setup)
import { reactive, ref } from 'vue';
const user = reactive({ name: '张三' }); // 对象
const count = ref(0); // 基本类型
const list = reactive([1, 2, 3]); // 数组
const updateData = () => {
user.age = 20; // 直接新增属性
count.value++;
list.push(4); // 直接修改
};
4. 问题:Vue2 项目迁移后如何优化性能?2025 实战方案?
答案:迁移 Vue3 后可通过以下方案进一步优化性能:
-
响应式优化:使用
shallowRef
/shallowReactive
避免深层劫持(适用于无需响应式的深层对象); -
渲染优化:
-
用
v-memo
缓存组件(避免不必要的重渲染); -
用
defineProps
的shallowRef
选项优化 Props 传递;
- 打包优化:
-
用 Vite 替代 Webpack(启动和构建速度提升 50%+);
-
用
rollup-plugin-visualizer
分析打包体积,剔除冗余依赖;
- 运行时优化:
-
用
onMounted
替代mounted
(配合组合 API 按需执行); -
用
unref
简化ref.value
访问;
v-memo
优化示例:
javascript
<template>
<!-- 仅当user.id变化时才重渲染 -->
<UserCard v-memo="[user.id]" :user="user" />
</template>
5. 问题:Vue3 迁移后的测试策略?2025 主流测试工具?
答案:2025 年 Vue3 测试以 "组件测试 + E2E 测试" 为主,主流工具组合:
-
组件测试:
Vitest
(替代 Jest,Vite 原生支持,速度更快)+@vue/test-utils@2
; -
E2E 测试:
Cypress
(模拟用户操作,检测端到端流程); -
类型测试:TypeScript 静态类型检查;
- Vitest 组件测试示例:
javascript
// tests/unit/UserCard.test.ts
import { mount } from '@vue/test-utils';
import UserCard from '@/components/UserCard.vue';
describe('UserCard', () => {
it('renders user name correctly', () => {
const user = { name: '张三', age: 20 };
const wrapper = mount(UserCard, {
props: { user }
});
// 断言用户名渲染正确
expect(wrapper.find('.name').text()).toBe('张三');
});
it('emits "edit" event when click edit button', () => {
const wrapper = mount(UserCard, {
props: { user: { id: 1, name: '张三' } }
});
// 点击编辑按钮
wrapper.find('.edit-btn').trigger('click');
// 断言事件触发
expect(wrapper.emitted('edit')).toHaveLength(1);
expect(wrapper.emitted('edit')[0]).toEqual([1]); // 传递用户ID
});
});
总结
2025 年 Vue 面试重点聚焦Vue3 核心特性 (Proxy 响应式、Composition API、Pinia)、生态新工具 (Alova、Vite)及实战迁移能力。本文覆盖 32 个高频考点,包含 15 段核心代码示例,建议结合自身项目经验补充案例,提升面试通过率。