2025前端面试题—Vue篇
好的!我将为你整理 100 道 Vue 面试题,覆盖 Vue2 和 Vue3 的核心知识点,并为每道题提供完整的代码块示例。题目将涵盖以下几个模块:
🧱 分类结构预览:
-
Vue 基础与模板语法
-
响应式系统
-
组件系统与通信
-
生命周期与钩子
-
Composition API(Vue3)
-
指令与条件渲染
-
事件处理与表单绑定
-
插槽与动态组件
-
状态管理(Vuex & Pinia)
-
Vue Router 与路由守卫
-
性能优化与技巧
-
TypeScript 与 Vue3
-
项目实践与部署
-
SSR 与 Nuxt
-
测试、调试与工具链
我们将按模块依次输出 100 道 Vue 面试题,每题包含:
-
✅ 面试题目
-
🔍 解析说明
-
📘 Vue2 示例
-
📘 Vue3 示例
✅ 模块一:Vue 基础与模板语法(1–10)
1. Vue 中如何实现数据的双向绑定?
🔍 解析:
Vue2 使用 v-model 实现 value 和 @input 的组合;Vue3 改为 modelValue + update:modelValue。
📘 Vue2 示例:
<template>
<input v-model="msg" />
</template>
<script>
export default {
data() {
return {
msg: ''
};
}
}
</script>
📘 Vue3 示例:
<!-- 父组件 -->
<MyInput v-model="msg" />
<!-- 子组件 -->
<template>
<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</template>
<script setup>
defineProps(['modelValue']);
defineEmits(['update:modelValue']);
</script>
2. Vue 的指令有哪些?
🔍 解析:
常用指令有:
-
v-bind:绑定属性 -
v-model:双向绑定 -
v-if/v-else/v-else-if:条件渲染 -
v-for:列表渲染 -
v-on:事件绑定 -
v-show:切换显示状态 -
v-html:插入 HTML
📘 示例:
<template>
<div v-if="isShow">Hello</div>
<button @click="isShow = !isShow">Toggle</button>
</template>
<script>
export default {
data() {
return { isShow: true };
}
}
</script>
3. v-if 和 v-show 有什么区别?
🔍 解析:
-
v-if是真正的条件渲染(DOM 创建与销毁) -
v-show是 display 的切换(性能更优)
📘 示例:
<template>
<div>
<p v-if="visible">使用 v-if</p>
<p v-show="visible">使用 v-show</p>
<button @click="visible = !visible">切换</button>
</div>
</template>
<script>
export default {
data() {
return { visible: true };
}
}
</script>
4. Vue 如何绑定 HTML 属性?
🔍 解析:
使用 v-bind 或简写 :。如 :src="url",:[attr]="value" 动态绑定属性名。
📘 示例:
<template>
<img :src="imgUrl" />
</template>
<script>
export default {
data() {
return {
imgUrl: 'https://example.com/logo.png'
};
}
}
</script>
5. v-for 的 key 为什么重要?
🔍 解析:
key 有助于 Vue 精确追踪节点,提升渲染效率,避免错误复用组件状态。
📘 示例:
<template>
<ul>
<li v-for="item in list" :key="item.id">{{ item.name }}</li>
</ul>
</template>
<script>
export default {
data() {
return {
list: [{ id: 1, name: 'A' }, { id: 2, name: 'B' }]
};
}
}
</script>
6. Vue 如何监听用户输入事件?
🔍 解析:
使用 v-on 或 @,监听事件如 @click、@input 等。
📘 示例:
<template>
<input @input="onInput" />
</template>
<script>
export default {
methods: {
onInput(e) {
console.log(e.target.value);
}
}
}
</script>
7. v-model 和 prop + emit 的区别?
🔍 解析:
-
v-model是语法糖(简洁) -
prop + emit是底层机制,更灵活
📘 Vue3 子组件使用:
<template>
<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</template>
<script setup>
defineProps(['modelValue']);
defineEmits(['update:modelValue']);
</script>
8. Vue 模板中如何使用三元表达式?
🔍 解析:
模板插值支持 JavaScript 表达式(不能有语句)。
📘 示例:
<template>
<p>{{ isAdmin ? '管理员' : '用户' }}</p>
</template>
<script>
export default {
data() {
return { isAdmin: true };
}
}
</script>
9. Vue 中的 computed 有什么作用?
🔍 解析:
-
计算属性,基于依赖缓存结果
-
适合纯函数型逻辑处理
📘 示例:
<template>
<p>总价:{{ total }}</p>
</template>
<script>
export default {
data() {
return { price: 100, count: 2 };
},
computed: {
total() {
return this.price * this.count;
}
}
}
</script>
10. Vue 中的 methods 和 computed 有什么区别?
🔍 解析:
-
computed有缓存,适合依赖数据变化的值 -
methods每次调用都重新计算
📘 对比示例:
<template>
<div>
<p>Computed: {{ doubleCount }}</p>
<p>Method: {{ getDoubleCount() }}</p>
</div>
</template>
<script>
export default {
data() {
return { count: 5 };
},
computed: {
doubleCount() {
console.log('computed');
return this.count * 2;
}
},
methods: {
getDoubleCount() {
console.log('method');
return this.count * 2;
}
}
}
</script>
✅ 模块二:响应式系统(11–20)
11. Vue 的响应式原理是什么?
🔍 解析:
-
Vue2 使用
Object.defineProperty()劫持 data 属性; -
Vue3 使用
Proxy实现响应式系统,更强大、可嵌套、支持数组等结构。
📘 Vue2 简化示例:
let data = {};
Object.defineProperty(data, 'msg', {
get() {
console.log('读取 msg');
return 'hello';
},
set(newVal) {
console.log('设置 msg', newVal);
}
});
data.msg = 'hi';
📘 Vue3 示例:
import { reactive, effect } from 'vue';
const state = reactive({ count: 0 });
effect(() => {
console.log('count 是:', state.count);
});
state.count++; // 触发依赖收集与响应
12. Vue3 中 reactive 和 ref 的区别?
🔍 解析:
| 对比 | reactive | ref |
|---|---|---|
| 类型 | 对象响应式 | 基本类型响应式(也可包对象) |
| 返回 | 响应式对象 | 包装对象(.value) |
| 使用场景 | 多属性对象 | 单值、布尔值、字符串等 |
📘 示例:
import { reactive, ref } from 'vue';
const obj = reactive({ a: 1 });
const num = ref(10);
console.log(obj.a); // 1
console.log(num.value); // 10
13. Vue 中 watch 与 computed 的区别?
🔍 解析:
-
computed是依赖值的衍生属性(有缓存) -
watch是监听副作用(执行回调)
📘 示例:
import { ref, watch, computed } from 'vue';
const count = ref(0);
const double = computed(() => count.value * 2);
watch(count, (newVal, oldVal) => {
console.log(`count 从 ${oldVal} 变为 ${newVal}`);
});
14. Vue2 如何实现响应式数组监听?
🔍 解析:
Vue2 中重写了数组的变更方法(如 push、splice、shift、pop 等),来实现响应式,但直接用 arr[0] = val 是不会响应的。
📘 示例:
let vm = new Vue({
data() {
return {
list: [1, 2, 3]
};
}
});
vm.list.push(4); // 可响应
vm.list[0] = 100; // 不可响应,需使用 $set
15. 如何深度监听对象变化?
🔍 解析:
使用 watch 的 deep: true 选项。
📘 示例:
watch(
() => state.obj,
(newVal) => {
console.log('对象发生变化', newVal);
},
{ deep: true }
);
16. 为什么 Vue2 不能监听对象新增属性?
🔍 解析:
Vue2 的响应式依赖 Object.defineProperty,只能劫持已存在属性,新增属性不会自动变成响应式。
📘 示例:
vm.obj.newKey = 123; // 无效
vm.$set(vm.obj, 'newKey', 123); // 有效
17. Vue3 是如何解决 Vue2 的响应式缺陷的?
🔍 解析:
Vue3 使用 Proxy 重构响应式系统,可代理整个对象,支持深层嵌套和属性动态添加。
📘 示例:
const state = reactive({});
state.a = 1; // 直接添加新属性也是响应式
18. ref 包装对象和 reactive 的区别?
🔍 解析:
-
ref({})返回的是对象的响应式包装(取值需.value) -
reactive({})直接返回响应式对象
📘 示例:
const obj1 = ref({ a: 1 });
const obj2 = reactive({ a: 1 });
console.log(obj1.value.a); // ref
console.log(obj2.a); // reactive
19. readonly 有什么作用?
🔍 解析:
readonly() 可创建只读响应式对象,适用于防止外部修改。
📘 示例:
import { reactive, readonly } from 'vue';
const state = reactive({ count: 0 });
const roState = readonly(state);
roState.count = 100; // 会提示警告
20. shallowReactive 和 shallowRef 有什么区别?
🔍 解析:
| API | 说明 |
|---|---|
shallowReactive |
只处理一层响应式 |
shallowRef |
ref,只追踪顶层 .value |
📘 示例:
import { shallowReactive, shallowRef } from 'vue';
const obj = shallowReactive({ nested: { num: 1 } });
const num = shallowRef(0);
obj.nested.num = 2; // 不响应
num.value = 10; // 响应
✅ 模块三:组件系统与通信(21–30)
21. 父组件如何向子组件传值?
🔍 解析:
使用 props 传递数据。
📘 Vue2 示例:
<!-- Parent.vue -->
<template>
<Child :msg="parentMsg" />
</template>
<script>
import Child from './Child.vue';
export default {
components: { Child },
data() {
return { parentMsg: 'hello from parent' };
}
};
</script>
<!-- Child.vue -->
<template>
<p>{{ msg }}</p>
</template>
<script>
export default {
props: ['msg']
};
</script>
📘 Vue3 示例:
<!-- Child.vue -->
<script setup>
defineProps(['msg']);
</script>
<template>
<p>{{ msg }}</p>
</template>
22. 子组件如何向父组件传值?
🔍 解析:
通过 $emit 或 Vue3 中的 defineEmits 触发自定义事件。
📘 Vue2 示例:
<!-- Child.vue -->
<template>
<button @click="$emit('customEvent', '子组件数据')">传值</button>
</template>
<!-- Parent.vue -->
<Child @customEvent="handleChildData" />
<script>
methods: {
handleChildData(data) {
console.log('来自子组件的数据:', data);
}
}
</script>
📘 Vue3 示例:
<!-- Child.vue -->
<script setup>
const emit = defineEmits(['customEvent']);
</script>
<template>
<button @click="emit('customEvent', 'Hello from child')">传值</button>
</template>
23. 非父子组件如何通信?
🔍 解析:
-
使用事件总线(Vue2 常用)
-
使用状态管理(Vuex / Pinia)
-
使用 provide/inject(父链传递)
📘 事件总线(Vue2):
// bus.js
import Vue from 'vue';
export const EventBus = new Vue();
// 组件A触发
EventBus.$emit('msg', 'hello');
// 组件B监听
EventBus.$on('msg', (val) => console.log(val));
24. 如何使用 provide 和 inject 实现通信?
🔍 解析:
适合祖孙组件通信;Vue2 支持基本用法,Vue3 更灵活。
📘 Vue3 示例:
<!-- 父组件 -->
<script setup>
import { provide } from 'vue';
provide('themeColor', 'red');
</script>
<!-- 孙组件 -->
<script setup>
import { inject } from 'vue';
const color = inject('themeColor');
</script>
<template><div :style="{ color }">文字</div></template>
25. Vue 组件的生命周期有哪些?
🔍 解析:
-
Vue2:
beforeCreate → created → beforeMount → mounted → beforeUpdate → updated → beforeDestroy → destroyed -
Vue3:组合式 API 中使用
onMounted()、onUnmounted()等
📘 Vue3 示例:
import { onMounted, onUnmounted } from 'vue';
onMounted(() => {
console.log('组件挂载');
});
onUnmounted(() => {
console.log('组件卸载');
});
26. Vue2 中的 keep-alive 有什么作用?
🔍 解析:
<keep-alive> 用于缓存组件状态,避免重复渲染,常用于 tab 页面或表单。
📘 示例:
<keep-alive>
<component :is="currentView" />
</keep-alive>
27. v-model 在自定义组件中如何实现?
🔍 解析:
-
Vue2:通过
valueprop +input事件 -
Vue3:使用
modelValue+update:modelValue
📘 Vue3 示例:
<!-- MyInput.vue -->
<script setup>
defineProps(['modelValue']);
defineEmits(['update:modelValue']);
</script>
<template>
<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</template>
28. 如何实现具名插槽?
🔍 解析:
插槽可以具名,适用于组件结构灵活时。
📘 示例:
<!-- MyLayout.vue -->
<template>
<header><slot name="header" /></header>
<main><slot /></main>
<footer><slot name="footer" /></footer>
</template>
<!-- 使用 -->
<MyLayout>
<template #header><h1>顶部</h1></template>
<p>中间内容</p>
<template #footer><p>底部</p></template>
</MyLayout>
29. 动态组件是如何实现的?
🔍 解析:
通过 <component :is="componentName" /> 实现动态切换组件。
📘 示例:
<template>
<component :is="currentComponent" />
</template>
<script>
import A from './A.vue';
import B from './B.vue';
export default {
data() {
return {
currentComponent: 'A'
};
},
components: { A, B }
}
</script>
30. 子组件如何访问父组件实例?
🔍 解析:
-
Vue2 可使用
this.$parent -
Vue3 推荐使用
provide/inject
📘 Vue2 示例:
mounted() {
console.log('父组件 msg:', this.$parent.msg);
}
⚠️ 注意:这是一种紧耦合方式,不推荐频繁使用。
✅ 模块四:生命周期与钩子(31–40)
31. Vue2 生命周期的执行顺序是什么?每个阶段做什么?
🔍 解析:
Vue2 生命周期顺序如下:
beforeCreate → created → beforeMount → mounted → beforeUpdate → updated → beforeDestroy → destroyed
📘 用途简要说明:
| 阶段 | 说明 |
|---|---|
| beforeCreate | 实例初始化,data/props 不可访问 |
| created | 已创建实例,可访问数据、methods,适合发请求 |
| beforeMount | 模板编译前 |
| mounted | DOM 已挂载,适合操作 DOM |
| beforeUpdate | 数据变更但 DOM 未更新 |
| updated | DOM 已完成更新 |
| beforeDestroy | 实例销毁前 |
| destroyed | 实例已销毁,事件解绑等 |
📘 示例代码:
export default {
beforeCreate() {
console.log('beforeCreate');
},
created() {
console.log('created');
},
mounted() {
console.log('mounted');
},
beforeDestroy() {
console.log('beforeDestroy');
},
destroyed() {
console.log('destroyed');
}
};
32. Vue3 的生命周期钩子如何写?
🔍 解析:
使用 Composition API 中的 onXxx() 函数。
📘 示例:
import { onMounted, onBeforeUnmount } from 'vue';
onMounted(() => {
console.log('组件已挂载');
});
onBeforeUnmount(() => {
console.log('组件即将卸载');
});
33. 在 mounted 和 created 中发请求有什么区别?
🔍 解析:
-
created:数据已初始化,但 DOM 未挂载 → 更快,适合数据准备 -
mounted:DOM 已挂载 → 若请求依赖 DOM,则用 mounted
📘 示例:
created() {
axios.get('/api/list').then(res => {
this.list = res.data;
});
}
34. 哪些生命周期在服务端渲染(SSR)中不会执行?
🔍 解析:
在 SSR 中,beforeMount、mounted、updated 等涉及 DOM 的生命周期不会被执行。
35. Vue3 中的 setup 是在什么时候执行的?
🔍 解析:
setup() 是在组件创建前执行的,是 Composition API 的入口,比 Vue2 的 created 更早,不能访问 this。
📘 示例:
<script setup>
console.log('setup 执行'); // 在生命周期最开始
</script>
36. 生命周期中做 DOM 操作应该选哪个钩子?
🔍 解析:
Vue2:mounted,因为此时 DOM 已插入
Vue3:onMounted
📘 Vue3 示例:
onMounted(() => {
const el = document.getElementById('myDiv');
console.log(el.innerText);
});
37. 如何监听组件销毁?可以做什么?
🔍 解析:
使用:
-
Vue2:
beforeDestroy,destroyed -
Vue3:
onBeforeUnmount,onUnmounted
📘 示例:
onBeforeUnmount(() => {
console.log('组件将被卸载');
});
常用于:
-
清理定时器
-
移除事件监听器
-
取消网络请求
38. Vue3 的 onUpdated 和 watchEffect 有什么区别?
🔍 解析:
-
onUpdated:在 DOM 更新后触发 -
watchEffect:响应式副作用追踪,更早触发,适用于数据变动时执行副作用逻辑
📘 示例:
watchEffect(() => {
console.log('数据变了,自动运行');
});
onUpdated(() => {
console.log('DOM 更新完毕');
});
39. 生命周期中哪些适合发请求?
🔍 解析:
-
Vue2:
created(推荐)、mounted(如果依赖 DOM) -
Vue3:
setup中直接写或用onMounted(推荐)
40. 如何在 Vue3 中封装通用的生命周期逻辑?
🔍 解析:
可通过 组合函数 封装生命周期逻辑,便于复用。
📘 示例:
// usePageLog.js
import { onMounted, onUnmounted } from 'vue';
export function usePageLog() {
onMounted(() => console.log('页面打开'));
onUnmounted(() => console.log('页面关闭'));
}
// 组件中使用
import { usePageLog } from './usePageLog';
usePageLog();
✅ 模块五:指令与模板语法(41–50)
41. Vue 的模板语法有哪些核心语法?
🔍 解析:
-
插值语法:
{{ msg }} -
指令语法:
v-bind,v-if,v-for,v-model,v-on等 -
缩写:
-
:=>v-bind: -
@=>v-on:
-
📘 示例:
<template>
<div :title="tip" v-if="visible">
{{ msg }}
</div>
</template>
42. v-if 和 v-show 有什么区别?使用场景?
🔍 解析:
| 特性 | v-if | v-show |
|---|---|---|
| 控制方式 | DOM 创建/销毁 | CSS 控制 display |
| 性能 | 切换频繁时性能差 | 切换频繁时性能优 |
| 初始渲染 | 不渲染隐藏部分 | 渲染后隐藏 |
📘 示例:
<p v-if="isLogin">欢迎回来</p>
<p v-show="isLogin">欢迎回来</p>
43. 如何使用 v-for 渲染列表?并说明 key 的作用。
🔍 解析:
-
v-for用于循环渲染数组/对象 -
key用于提升虚拟 DOM 更新效率,应避免使用索引
📘 示例:
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
44. 如何监听用户输入?
🔍 解析:
-
使用
v-model实现双向绑定 -
可搭配
@input,@change等事件精细控制
📘 示例:
<input v-model="msg" @input="handleInput" />
45. v-bind 的用法有哪些?可以绑定什么?
🔍 解析:
-
用于绑定 HTML 属性、组件 props、样式、class 等
-
可单个或对象绑定
📘 示例:
<!-- 单个 -->
<img :src="imgUrl" />
<!-- 对象绑定 style -->
<div :style="{ color: textColor, fontSize: size + 'px' }"></div>
<!-- 绑定 class -->
<div :class="{ active: isActive }"></div>
46. Vue 的事件修饰符有哪些?
🔍 解析:
| 修饰符 | 含义 |
|---|---|
.stop |
阻止冒泡 |
.prevent |
阻止默认行为 |
.once |
事件只触发一次 |
.capture |
使用捕获模式 |
.self |
仅在自身上触发 |
.native |
子组件绑定原生事件(Vue2) |
📘 示例:
<button @click.stop.prevent="handleClick">点击</button>
47. 如何使用修饰符限制 v-model 的行为?
🔍 解析:
-
.lazy: 在change而非input时更新 -
.number: 自动将输入转为 number -
.trim: 自动去除首尾空格
📘 示例:
<input v-model.lazy="msg" />
<input v-model.number="age" />
<input v-model.trim="username" />
48. 如何定义自定义指令?
🔍 解析:
📘 Vue2:
Vue.directive('focus', {
inserted(el) {
el.focus();
}
});
📘 Vue3:
const app = createApp(App);
app.directive('focus', {
mounted(el) {
el.focus();
}
});
📘 使用:
<input v-focus />
49. 如何使用模板引用(ref)访问 DOM 或组件?
🔍 解析:
-
Vue2:使用
$refs -
Vue3:
ref()+onMounted
📘 Vue2:
<input ref="input" />
this.$refs.input.focus();
📘 Vue3:
<script setup>
import { ref, onMounted } from 'vue';
const inputRef = ref(null);
onMounted(() => inputRef.value.focus());
</script>
<template>
<input ref="inputRef" />
</template>
50. 如何使用 v-html 渲染 HTML?有哪些风险?
🔍 解析:
-
作用:将字符串渲染为 HTML
-
风险:可能造成 XSS 攻击,须谨慎使用
📘 示例:
<div v-html="rawHtml"></div>
⚠️ 避免直接渲染用户输入的内容,应过滤后使用。
✅ 模块六:Vue Router 与路由管理(51–60)
51. Vue Router 是什么?
🔍 解析:
Vue Router 是 Vue 官方的路由管理器,实现单页面应用(SPA)页面导航和状态管理,支持 URL 路由映射、嵌套路由、导航守卫等。
52. 如何在 Vue2 中安装并使用 Vue Router?
📘 示例:
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from './views/Home.vue';
Vue.use(VueRouter);
const routes = [
{ path: '/', component: Home }
];
const router = new VueRouter({
routes
});
new Vue({
router,
render: h => h(App)
}).$mount('#app');
53. Vue3 如何使用 Vue Router 4?
📘 示例:
import { createApp } from 'vue';
import { createRouter, createWebHistory } from 'vue-router';
import App from './App.vue';
import Home from './views/Home.vue';
const routes = [{ path: '/', component: Home }];
const router = createRouter({
history: createWebHistory(),
routes
});
const app = createApp(App);
app.use(router);
app.mount('#app');
54. 什么是动态路由?如何定义?
🔍 解析:
动态路由是带参数的路由,路径中包含变量(如 :id),用于匹配不同参数。
📘 示例:
const routes = [
{ path: '/user/:id', component: User }
];
访问 /user/123,id 为 123。
55. 如何获取路由参数?
📘 Vue2:
this.$route.params.id
📘 Vue3:
import { useRoute } from 'vue-router';
const route = useRoute();
console.log(route.params.id);
56. 路由导航守卫是什么?有哪些类型?
🔍 解析:
用于控制路由访问权限,常用于鉴权。
类型:
-
全局守卫:
beforeEach、afterEach -
路由独享守卫:
beforeEnter -
组件内守卫:
beforeRouteEnter、beforeRouteLeave、beforeRouteUpdate
57. 如何实现路由懒加载?
🔍 解析:
使用动态导入,减少首屏加载体积。
📘 示例:
const Home = () => import('./views/Home.vue');
const routes = [
{ path: '/', component: Home }
];
58. 路由如何实现嵌套?
🔍 解析:
通过子路由实现嵌套,父组件内放置 <router-view>。
📘 示例:
const routes = [
{
path: '/parent',
component: Parent,
children: [
{ path: 'child', component: Child }
]
}
];
59. Vue Router 如何编程式导航?
📘 示例:
// Vue2
this.$router.push('/home');
// Vue3
import { useRouter } from 'vue-router';
const router = useRouter();
router.push('/home');
60. 如何实现路由重定向?
📘 示例:
const routes = [
{ path: '/home', component: Home },
{ path: '/', redirect: '/home' }
];
✅ 模块七:状态管理 Vuex / Pinia(61–70)
61. 什么是 Vuex?它解决了什么问题?
🔍 解析:
Vuex 是 Vue 官方的状态管理库,解决多组件间共享状态复杂的问题,集中管理应用的状态,便于维护和调试。
62. Vuex 的核心概念有哪些?
-
State:存储状态
-
Getters:计算衍生状态
-
Mutations:同步修改状态
-
Actions:异步操作,提交 mutations
-
Modules:分模块管理状态
63. Vue2 中如何安装使用 Vuex?
📘 示例:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: { count: 0 },
mutations: {
increment(state) {
state.count++;
}
}
});
new Vue({
store,
render: h => h(App)
}).$mount('#app');
64. Vue3 中如何使用 Vuex?
📘 示例:
import { createApp } from 'vue';
import { createStore } from 'vuex';
import App from './App.vue';
const store = createStore({
state() {
return { count: 0 };
},
mutations: {
increment(state) {
state.count++;
}
}
});
const app = createApp(App);
app.use(store);
app.mount('#app');
65. 如何使用 Vuex 的 state 和 mutations?
📘 示例:
// 访问 state
computed: {
count() {
return this.$store.state.count;
}
},
// 调用 mutation
methods: {
increment() {
this.$store.commit('increment');
}
}
66. Vuex 中 actions 的作用是什么?
🔍 解析:
用于封装异步逻辑,通过 commit 调用 mutations。
📘 示例:
actions: {
asyncIncrement({ commit }) {
setTimeout(() => {
commit('increment');
}, 1000);
}
}
67. 什么是 Vuex 的 getters?
🔍 解析:
类似计算属性,用于从 state 派生数据。
📘 示例:
getters: {
doubleCount(state) {
return state.count * 2;
}
}
组件内:
computed: {
doubleCount() {
return this.$store.getters.doubleCount;
}
}
68. Vue3 推荐使用什么状态管理库替代 Vuex?
🔍 解析:
Pinia,被官方推荐为 Vue3 生态的状态管理库,API 更简洁,支持 TS。
69. 如何在 Vue3 中安装和使用 Pinia?
📘 示例:
import { createApp } from 'vue';
import { createPinia, defineStore } from 'pinia';
import App from './App.vue';
const pinia = createPinia();
const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
actions: {
increment() {
this.count++;
}
}
});
const app = createApp(App);
app.use(pinia);
app.mount('#app');
组件内使用:
import { useCounterStore } from './stores/counter';
const counter = useCounterStore();
counter.increment();
70. Pinia 和 Vuex 的主要区别是什么?
| 特性 | Vuex | Pinia |
|---|---|---|
| API | 复杂,需分为 state/mutations/actions/getters | 简洁,store 统一管理状态和方法 |
| 类型支持 | 较弱 | 优秀,支持 TS |
| 设计理念 | Flux 风格 | 更灵活,类似 Composition API |
| 模块管理 | 通过 modules | 通过多个 store |
✅ 模块八:性能优化与工程化(71–80)
71. 什么是前端性能优化?为什么重要?
🔍 解析:
前端性能优化是提升页面加载速度、响应速度和用户体验的技术手段。提升性能能减少用户等待时间,降低跳出率。
72. Vue 应用中常见的性能瓶颈有哪些?
-
大量不必要的组件重新渲染
-
频繁的 DOM 操作
-
资源(JS/CSS/图片)体积过大
-
不合理的事件监听
73. 如何避免 Vue 组件的重复渲染?
🔍 解析:
-
使用
v-once静态内容只渲染一次 -
合理使用
key确保列表高效渲染 -
使用计算属性代替复杂表达式
-
使用
shouldComponentUpdate(Vue 没有此 API,但可用watch和computed优化)
74. Vue 中如何使用 keep-alive?
🔍 解析:
<keep-alive> 缓存组件状态,避免组件重复渲染,常用于路由组件。
📘 示例:
<keep-alive>
<router-view />
</keep-alive>
75. 什么是懒加载?Vue 如何实现?
🔍 解析:
懒加载指按需加载资源,减少初始包体积。
📘 示例(路由懒加载):
const Home = () => import('./views/Home.vue');
76. Vue 如何减少事件监听器的性能消耗?
🔍 解析:
-
使用事件修饰符
.once,减少事件绑定次数 -
委托事件,避免给多个元素绑定事件
-
使用节流(throttle)或防抖(debounce)优化频繁触发事件
77. 如何用代码分割优化 Vue 应用?
🔍 解析:
利用动态 import 使代码拆分成多个包,按需加载。
78. Vue 组件内如何避免过度 watch?
🔍 解析:
只监听必要的数据,避免监听整个对象或数组,减少无效响应。
79. 前端资源压缩和缓存策略有哪些?
-
JS/CSS 压缩混淆
-
图片压缩
-
合理设置 Cache-Control
-
使用 Service Worker 缓存静态资源
80. 如何使用 Vue CLI 优化生产环境构建?
🔍 解析:
-
配置
vue.config.js开启 gzip -
配置按需加载
-
配置打包分析工具
✅ 模块九:综合应用与实战(81–90)
81. 如何在 Vue 中实现表单验证?
🔍 解析:
可使用第三方库如 VeeValidate、 vuelidate,也可手写校验逻辑结合 watch 或 computed。
📘 示例(简单示范):
<template>
<input v-model="email" @blur="validateEmail" />
<p v-if="error">{{ error }}</p>
</template>
<script>
export default {
data() {
return {
email: '',
error: ''
}
},
methods: {
validateEmail() {
const re = /\S+@\S+\.\S+/;
this.error = re.test(this.email) ? '' : '邮箱格式错误';
}
}
}
</script>
82. Vue 中如何实现父子组件双向绑定?
🔍 解析:
使用 .sync 修饰符或自定义 v-model 实现。
📘 示例(Vue2 使用 .sync):
<!-- 父组件 -->
<child-component :value="msg" @update:value="val => msg = val" />
<!-- 子组件 -->
<template>
<input :value="value" @input="$emit('update:value', $event.target.value)" />
</template>
<script>
export default {
props: ['value']
}
</script>
83. 如何解决 Vue 组件通信层级深的问题?
🔍 解析:
-
使用 Vuex 或 Pinia 进行全局状态管理
-
使用 provide/inject 传递数据
-
事件总线(Vue2),但不推荐
84. Vue3 Composition API 中如何组织大型项目状态?
🔍 解析:
利用 setup() 函数搭配 reactive 或 ref,并结合 Pinia 组织状态。
85. 如何在 Vue 中实现国际化(i18n)?
🔍 解析:
使用 vue-i18n 插件,配置语言包和切换方法。
📘 示例:
import { createI18n } from 'vue-i18n';
const messages = {
en: { welcome: 'Welcome' },
zh: { welcome: '欢迎' }
};
const i18n = createI18n({
locale: 'en',
messages
});
86. Vue 如何处理表单控件的默认值?
🔍 解析:
用 v-model 绑定初始数据,且在 data 或 setup 中设置默认值。
87. Vue 组件中的 $nextTick 有什么用?
🔍 解析:
在数据更新且 DOM 更新完成后执行回调,常用于操作更新后的 DOM。
📘 示例:
this.msg = '更新';
this.$nextTick(() => {
console.log('DOM 已更新');
});
88. Vue3 如何使用 Suspense 处理异步组件?
🔍 解析:
使用 <Suspense> 包裹异步组件,支持加载状态和错误边界。
📘 示例:
<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div>加载中...</div>
</template>
</Suspense>
89. Vue 如何实现自定义事件?
🔍 解析:
子组件通过 $emit 触发事件,父组件监听。
📘 示例:
<!-- 子组件 -->
<button @click="$emit('custom-click')">点我</button>
<!-- 父组件 -->
<child-component @custom-click="handleClick" />
90. Vue 组件生命周期有哪些?
🔍 解析:
| 生命周期钩子 | 作用 |
|---|---|
| beforeCreate | 实例初始化,数据观测之前 |
| created | 实例创建,数据观测后 |
| beforeMount | 挂载开始前 |
| mounted | 挂载完成 |
| beforeUpdate | 数据更新前 |
| updated | 数据更新后 |
| beforeUnmount | 卸载前(Vue3) |
| unmounted | 卸载后(Vue3) |
✅ 模块十:Vue3 新特性(91–100)
91. Vue3 中的 Composition API 是什么?
🔍 解析:
Composition API 是 Vue3 新增的 API,提供更灵活的逻辑复用和代码组织方式,通过 setup() 函数实现组件逻辑组织。
92. Vue3 中 ref 和 reactive 的区别?
🔍 解析:
-
ref用于基本类型,返回带.value的响应式引用。 -
reactive用于对象,返回响应式代理。
📘 示例:
import { ref, reactive } from 'vue';
const count = ref(0);
const state = reactive({ count: 0 });
93. 如何在 Vue3 中使用 watch 监听响应式数据?
📘 示例:
import { ref, watch } from 'vue';
const count = ref(0);
watch(count, (newVal, oldVal) => {
console.log(`count 从 ${oldVal} 变为 ${newVal}`);
});
94. 什么是 Vue3 的 Teleport?
🔍 解析:
Teleport 用于将组件内容传送到 DOM 的另一个位置,常用于模态框、弹窗。
📘 示例:
<Teleport to="body">
<div class="modal">弹窗内容</div>
</Teleport>
95. Vue3 如何实现自定义指令?
📘 示例:
const app = createApp(App);
app.directive('focus', {
mounted(el) {
el.focus();
}
});
96. Vue3 中的 Suspense 作用?
🔍 解析:
Suspense 用于处理异步组件加载状态,支持 fallback 和错误边界。
97. Vue3 中 emits 选项的作用?
🔍 解析:
声明组件可触发的事件,提高类型推断和代码可维护性。
📘 示例:
export default {
emits: ['update']
}
98. Vue3 中 setup 函数的返回值有什么作用?
🔍 解析:
setup 返回的对象中属性可在模板中直接使用。
99. Vue3 中如何处理多个响应式数据依赖?
🔍 解析:
通过 computed 组合多个响应式数据。
📘 示例:
import { reactive, computed } from 'vue';
const state = reactive({ a: 1, b: 2 });
const sum = computed(() => state.a + state.b);
100. Vue3 如何使用 Provide / Inject 传递状态?
📘 示例:
// 祖先组件
import { provide } from 'vue';
setup() {
provide('key', 'value');
}
// 子组件
import { inject } from 'vue';
setup() {
const val = inject('key');
}
全部 100 道 Vue(含 Vue2/3)面试题及详解完成!

浙公网安备 33010602011771号