1. Vue 的核心是什么?
Vue 的核心主要包含两点:
- **数据驱动(Data-Driven)**:视图由数据状态决定,数据变更自动更新 DOM,无需手动操作 DOM;
- **组件化(Component-Based)**:将页面拆分为独立、可复用的组件,降低耦合度,提升开发效率;
- 补充:核心还包括响应式系统、虚拟 DOM 等底层支撑能力。
2. 请简述你对 Vue 的理解
Vue 是一套渐进式 JavaScript 框架,核心定位是“渐进式”——可以按需使用核心功能(如响应式、组件),也可结合路由(Vue Router)、状态管理(Vuex/Pinia)等生态扩展复杂应用;
- 设计理念:轻量、易用、高效,兼顾开发体验和运行性能;
- 核心特性:响应式数据绑定、组件化、指令系统、虚拟 DOM、生命周期等;
- 应用场景:从简单的表单页面到复杂的单页应用(SPA)均可覆盖,是前端主流框架之一。
3. 请简述 Vue 的单向数据流
Vue 的单向数据流核心规则:数据只能从父组件流向子组件,子组件不能直接修改父组件传递的 props;
- 具体表现:
- 父组件通过 props 向子组件传值,子组件只读 props,不能直接修改;
- 若子组件需修改数据,需通过触发父组件的自定义事件,由父组件修改源数据,再反向更新子组件 props;
- 目的:保证数据流向可追溯,避免多个组件随意修改数据导致状态混乱,符合“单向绑定”的设计思想。
4. Vue 常用的修饰符有哪些
Vue 的修饰符按用途可分为三类,核心常用如下:
| 事件修饰符 | .stop、.prevent、.once | .stop 阻止事件冒泡,.prevent 阻止默认行为,.once 只触发一次 |
| 按键修饰符 | .enter、.esc、.tab | 监听特定按键触发事件(如 @keyup.enter) |
| 表单修饰符 | .trim、.number、.lazy | .trim 去除输入首尾空格,.number 转为数字,.lazy 失去焦点后更新数据 |
| 鼠标修饰符 | .left、.right、.middle | 监听鼠标特定按键(左键/右键/中键) |
5. v-text 与 {{}}的区别
两者均用于渲染文本,核心区别:
- **{{}}(插值表达式)**:
- 可嵌入 HTML 标签内(如 <div>姓名:{{name}}</div>);
- 存在“闪烁问题”(页面加载时可能先显示 {{name}} 再渲染值,可通过 v-cloak 解决);
- 支持简单表达式(如 {{age + 1}});
- v-text:
- 是指令,需直接绑定在标签上(如 <div v-text="name"></div>);
- 无闪烁问题,覆盖标签内所有内容(包括子节点);
- 不支持复杂表达式,仅接收变量/简单值;
- 补充:两者均会转义 HTML(若需渲染 HTML 用 v-html)。
6. v-on 可以绑定多个方法吗?
可以,有两种实现方式:
- 方式 1:绑定一个方法数组(Vue 2.4+ 支持)<button @click="[handleClick1, handleClick2]()">点击触发多个方法</button>
- 方式 2:绑定一个统一方法,内部调用多个子方法<button @click="handleAll">点击触发多个方法</button>
<script>
export default {
methods: {
handleAll() {
this.handleClick1();
this.handleClick2();
},
handleClick1() { /* 逻辑1 */ },
handleClick2() { /* 逻辑2 */ }
}
}
</script> - 注意:数组方式中方法需加 () 执行,否则仅定义不触发。
7. Vue 循环的 key 作用
key 是 Vue 列表渲染的核心属性,作用:
- 唯一标识节点:Vue 根据 key 判断节点是否为同一节点,避免复用错误(如输入框值错乱);
- 提升更新效率:当列表数据变化时,Vue 通过 key 精准定位需要更新的节点,而非重新渲染整个列表;
- 注意:
- key 需用唯一值(如 id),避免用 index(index 会随数据顺序变化,失去标识意义);
- 无 key 时 Vue 会采用“就地更新”策略,可能导致 DOM 复用异常。
8. 什么是计算属性?
计算属性(computed)是 Vue 用于处理派生数据的特性,基于依赖数据动态计算值:
- 核心特性:
- 缓存性:依赖数据不变时,多次访问计算属性只会执行一次计算,提升性能;
- 响应式:依赖数据变化时,计算属性自动重新计算并更新视图;
- 支持 get/set(默认 get,set 可手动修改依赖数据);
- 示例:<script>
export default {
data() {
return { a: 1, b: 2 };
},
computed: {
sum() { // 只读计算属性
return this.a + this.b;
},
fullName: { // 可读写计算属性
get() { return this.firstName + ' ' + this.lastName; },
set(val) { const [first, last] = val.split(' '); this.firstName = first; this.lastName = last; }
}
}
}
</script>
9. Vue 单页面(SPA)的优缺点
| 1. 无页面刷新,体验接近原生 App | 1. 首屏加载慢(需加载整包 JS/CSS) |
| 2. 组件化复用性高 | 2. SEO 不友好(页面内容动态渲染) |
| 3. 前后端分离,开发效率高 | 3. 路由切换需手动处理缓存/滚动 |
| 4. 数据管理更集中 | 4. 打包体积大,需按需加载优化 |
10. Vuex 是什么?怎么使用?在哪些场景下使用?
- 定义:Vuex 是 Vue 官方的集中式状态管理库,用于管理多组件共享的状态(如用户信息、全局配置);
- 使用步骤:
- 安装:npm install vuex –save;
- 创建 store:import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: { count: 0 }, // 状态
mutations: { increment(state) { state.count++ } }, // 同步修改状态
actions: { asyncIncrement({ commit }) { setTimeout(() => commit('increment'), 1000) } }, // 异步操作
getters: { doubleCount(state) { return state.count * 2 } }, // 派生状态
modules: { /* 模块拆分 */ }
}); - 挂载到 Vue 实例:new Vue({ store, … });
- 组件中使用:
- 读取 state:this.$store.state.count 或 mapState 辅助函数;
- 修改 state:this.$store.commit('increment')(同步)/ this.$store.dispatch('asyncIncrement')(异步);
- 多组件共享同一状态(如购物车、用户登录状态);
- 组件层级深,props/emit 传值繁琐;
- 需要追踪状态变更(Vuex 可记录状态修改日志)。
11. Vuex 与 Pinia 的区别
Pinia 是 Vue 3 推荐的状态管理库,替代 Vuex 4,核心区别:
| 核心结构 | 分 state/mutations/actions/getters/modules | 仅 state/actions/getters(无 mutations/modules) |
| 模块化 | 需通过 modules 嵌套,命名空间复杂 | 每个 store 独立,天然模块化,无需命名空间 |
| TypeScript | 支持差,需手动类型声明 | 原生支持 TS,类型推断更友好 |
| 代码简洁度 | 冗余(如 mutations 必须同步) | 简洁(actions 可同步/异步,无需 commit) |
| Vue 版本支持 | Vue 2/3(Vuex 3 对应 Vue 2,Vuex 4 对应 Vue 3) | 主要支持 Vue 3(也可兼容 Vue 2) |
| 调试 | 依赖 Vue Devtools,需配置 | 原生集成 Vue Devtools,调试更友好 |
12. Vue 路由的跳转方式
Vue Router 的跳转分两类:声明式(模板)和编程式(JS):
- **声明式()**:<!– 基础跳转 –>
<router-link to="/home">首页</router-link>
<!– 带参数 –>
<router-link :to="{ path: '/user', query: { id: 1 } }">用户页</router-link>
<router-link :to="{ name: 'User', params: { id: 1 } }">用户页</router-link> - **编程式($router.push/replace/go)**:// 基础跳转
this.$router.push('/home');
// 带query参数(路径拼接,如/user?id=1)
this.$router.push({ path: '/user', query: { id: 1 } });
// 带params参数(需路由配置name,如/user/1)
this.$router.push({ name: 'User', params: { id: 1 } });
// 替换当前历史记录(不新增历史)
this.$router.replace('/home');
// 前进/后退
this.$router.go(-1); // 后退一页
13. 跨域的解决方式
跨域是浏览器同源策略限制(协议、域名、端口任一不同即跨域),前端常用解决方案:
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000', // 后端接口地址
changeOrigin: true, // 开启跨域
pathRewrite: { '^/api': '' } // 重写路径
}
}
}
}
14. Vue 生命周期请简述
Vue 生命周期是组件从创建到销毁的全过程,分 8 个核心阶段(Vue 2):
- Vue 3 补充:组合式 API 中用 onMounted/onUpdated 等钩子替代选项式,新增 setup(替代 beforeCreate/created)。
15. Vue 生命周期的作用
生命周期钩子允许开发者在组件不同阶段插入自定义逻辑,核心作用:
16. DOM 渲染在哪个生命周期阶段内完成
- 核心结论:mounted 阶段完成 DOM 渲染;
- 细节:
- beforeMount:模板已编译,但未挂载到 DOM($el 为虚拟 DOM);
- mounted:真实 DOM 挂载完成,$el 指向真实 DOM 节点,可安全操作 DOM;
- 若组件包含子组件,mounted 仅表示当前组件 DOM 挂载完成,子组件可能仍在挂载中。
17. Vue 路由的实现
Vue Router 的核心实现依赖前端路由原理,分两步:
- 补充:路由模式(hash/history)决定 URL 的表现形式,底层分别基于 hashchange 事件和 History API。
18. 简述 Vue 路由模式 hash 和 history
| URL 表现 | 带#(如 http://xxx/#/home) | 无#(如 http://xxx/home) |
| 底层原理 | 基于 hashchange 事件,#后的内容不会发送到服务器 | 基于 HTML5 History API(pushState/replaceState) |
| 服务器配置 | 无需配置,刷新页面不会 404 | 需配置后端,刷新页面需重定向到 index.html(否则 404) |
| 兼容性 | 兼容所有浏览器(包括 IE) | 仅支持 HTML5 浏览器 |
| SEO | 部分搜索引擎不识别#后内容 | 更友好,SEO 效果更好 |
19. Vue 路由传参方式,params 与 query 方式和区别
- 传参方式:分 query 和 params 两种核心方式,均支持声明式/编程式;
- 核心区别:
| URL 表现 | 拼接在路径后(?key=value) | 嵌入路径中(/user/1) |
| 路由配置 | 无需特殊配置 | 需在路由 path 中定义(如/user/:id) |
| 刷新页面 | 参数不会丢失 | 若路由未定义参数,刷新后丢失 |
| 取值方式 | this.$route.query.key | this.$route.params.key |
| 可选性 | 可传可不传 | 路由定义的参数必须传(否则跳转失败) |
- 示例:// query传参
this.$router.push({ path: '/user', query: { id: 1 } }); // URL: /user?id=1
// params传参(需路由name)
this.$router.push({ name: 'User', params: { id: 1 } }); // URL: /user/1
20. Vue 数据绑定的几种方式
Vue 数据绑定分三类,核心是响应式绑定:
21. Vue 注册一个全局组件
全局组件注册后,所有 Vue 实例/组件均可直接使用,步骤:
// 1. 定义组件
const MyComponent = {
template: `<div>{{msg}}</div>`,
data() {
return { msg: '全局组件' };
}
};
// 2. 注册全局组件(Vue 2)
import Vue from 'vue';
Vue.component('MyComponent', MyComponent);
// Vue 3(createApp方式)
import { createApp } from 'vue';
const app = createApp({});
app.component('MyComponent', MyComponent);
app.mount('#app');
- 注意:全局组件需在 Vue 实例创建前注册,否则无法使用。
22. Vue 的路由钩子/路由守卫有哪些
Vue Router 的路由守卫分三类,用于控制路由跳转权限:
{
path: '/user',
component: User,
beforeEnter: (to, from, next) => { // 仅/user路由生效
if (/* 验证 */) next();
else next('/login');
}
}
];
23. Vue 中如何进行动态路由设置?有哪些方式?怎么获取传递过来的参数?
- 动态路由定义:在路由 path 中用 :参数名 定义,匹配任意值;
- 定义方式:// 1. 基础动态路由
const routes = [
{ path: '/user/:id', name: 'User', component: User }
];
// 2. 可选参数(加?)
{ path: '/user/:id?', component: User }
// 3. 通配符(匹配所有)
{ path: '*', component: NotFound } - 获取参数:
- 组件内通过 this.$route.params 获取(如 this.$route.params.id);
- 组合式 API 中用 useRoute:import { useRoute } from 'vue-router';
const route = useRoute();
console.log(route.params.id);
24. Element UI 中常用组件有哪些?请简述并说下他们的属性有哪些
Element UI 是 Vue 2 主流 UI 库,核心常用组件及属性:
| Button | 按钮 | type(primary/success)、size(small/medium)、disabled、icon |
| Input | 输入框 | v-model、placeholder、disabled、clearable、type(text/password) |
| Table | 表格 | data(数据源)、columns(列配置)、pagination(分页)、border、height |
| Form | 表单 | model(表单数据)、rules(校验规则)、label-width、inline |
| Dialog | 弹窗 | visible(显示/隐藏)、title、width、modal(遮罩)、close-on-click-modal |
| Select | 下拉选择 | v-model、options(选项)、multiple(多选)、disabled |
| Pagination | 分页 | total(总条数)、page-size(每页条数)、current-page(当前页)、layout(布局) |
25. Vue CLI 中如何自定义指令
自定义指令用于扩展 DOM 操作,分全局/局部指令:
- 全局自定义指令(main.js):// Vue 2
import Vue from 'vue';
// 注册v-focus指令(自动聚焦输入框)
Vue.directive('focus', {
inserted(el) { // 指令绑定到元素并插入DOM时触发
el.focus();
}
});// Vue 3
import { createApp } from 'vue';
const app = createApp({});
app.directive('focus', {
mounted(el) { el.focus(); }
}); - 局部自定义指令(组件内):<script>
export default {
directives: {
focus: {
inserted(el) { el.focus(); }
}
}
}
</script> - 指令钩子:bind(绑定)、inserted(插入 DOM)、update(更新)等(Vue 3 调整为 created/mounted/updated)。
26. Vue 中指令有哪些
Vue 指令分内置指令和自定义指令,核心内置指令:
| 数据绑定 | v-text、v-html、v-bind | 渲染文本/HTML、绑定属性 |
| 事件绑定 | v-on | 绑定事件(简写 @) |
| 双向绑定 | v-model | 表单数据双向绑定 |
| 条件渲染 | v-if、v-else、v-show | 条件显示/隐藏 DOM |
| 列表渲染 | v-for | 循环渲染列表 |
| 其他 | v-once、v-cloak、v-pre | 一次性绑定、解决闪烁、跳过编译 |
27. Vue 如何定义一个过滤器
过滤器用于格式化数据(Vue 3 已移除,推荐用计算属性/方法替代),Vue 2 定义方式:
- 全局过滤器(main.js):import Vue from 'vue';
// 注册全局过滤器(格式化时间)
Vue.filter('formatTime', (value) => {
return new Date(value).toLocaleString();
}); - 局部过滤器(组件内):<script>
export default {
filters: {
formatTime(value) {
return new Date(value).toLocaleString();
}
}
}
</script> - 使用:{{ time | formatTime }} 或 v-bind:title="time | formatTime"。
28. 对 Vue 中 keep-alive 的理解
keep-alive 是 Vue 的内置组件,用于缓存组件实例,避免重复创建/销毁:
- 核心特性:
- 包裹动态组件时,缓存不活动的组件,而非销毁;
- 触发组件的 activated(激活)/deactivated(失活)钩子;
- 常用属性:
- include:仅缓存指定组件(如 include="User,Home");
- exclude:排除指定组件;
- max:最大缓存数量(超出则销毁最久未使用的组件);
- 应用场景:路由切换时缓存表单数据、列表滚动位置等(如 <keep-alive><router-view></router-view></keep-alive>)。
29. 如何让组件中的 CSS 在当前组件生效
通过样式隔离实现,核心方式:
scoped 属性(推荐):
<style scoped>
.box { color: red; } // 仅当前组件生效
</style>
CSS Modules:
<style module>
.box { color: red; }
</style>
<template>
<div :class="$style.box">内容</div>
</template>
深度选择器(如需修改子组件样式):
<style scoped>
::v-deep .child-box { color: blue; } // Vue 2
:deep(.child-box) { color: blue; } // Vue 3
</style>
30. Vue 生命周期一共有几个阶段
- Vue 2:分 4 个大阶段,8 个核心钩子:
- 创建阶段(2 个):beforeCreate、created;
- 挂载阶段(2 个):beforeMount、mounted;
- 更新阶段(2 个):beforeUpdate、updated;
- 销毁阶段(2 个):beforeDestroy、destroyed;
- 补充:还有 activated/deactivated(keep-alive 组件)、errorCaptured(错误捕获)等钩子;
- Vue 3:组合式 API 中钩子更细分,核心阶段一致,钩子名调整为 onXxx(如 onMounted),新增 setup(替代 beforeCreate/created)。
31. MVVM 和 MVC 的区别
两者均为软件架构模式,核心区别:
| 核心角色 | Model(数据)、View(视图)、Controller(控制器,连接 M/V) | Model(数据)、View(视图)、ViewModel(桥梁,双向绑定) |
| 数据流向 | 单向(Model→Controller→View) | 双向(View←→ViewModel←→Model) |
| 耦合度 | View 和 Model 需通过 Controller 通信,耦合较高 | View 和 Model 完全解耦,由 ViewModel 中转 |
| 核心特性 | 手动更新视图(需 Controller 操作 DOM) | 自动更新视图(数据驱动,ViewModel 实现响应式) |
| 应用框架 | jQuery、Backbone.js | Vue、React(类 MVVM)、Angular |
32. Vue 组件中的 data 为什么是函数
核心原因:保证组件实例的独立性,避免多个组件实例共享同一数据对象;
- 原理:
- 若 data 是对象,所有组件实例会引用同一个对象,修改一个实例的 data 会影响其他实例;
- 若 data 是函数,每次创建组件实例时,函数返回一个新的对象,各实例数据独立;
- 示例:<script>
export default {
// 正确:函数返回新对象
data() {
return { count: 0 };
},
// 错误:所有实例共享count
// data: { count: 0 }
}
</script> - 补充:根实例(new Vue({}))的 data 可以是对象(仅一个实例,无共享问题)。
33. Vue 双向绑定原理
Vue 2 基于Object.defineProperty,Vue 3 基于Proxy,核心流程:
- Vue 2:
- 数据劫持:通过 Object.defineProperty 监听 data 中所有属性的 get/set;
- 依赖收集:模板编译时,访问属性触发 get,收集依赖(Watcher);
- 派发更新:修改属性触发 set,通知 Watcher 更新视图;
- 缺陷:无法监听数组下标/长度变化、对象新增属性;
- Vue 3:
- 数据代理:通过 Proxy 代理整个 data 对象,支持监听数组/对象所有变化;
- 依赖收集/派发更新逻辑与 Vue 2 类似,但效率更高;
- 核心公式:MVVM = 数据劫持 + 发布-订阅模式。
34. Vue 组件中的传值方式
组件传值分 7 种核心场景,覆盖父子/兄弟/跨级:
| 父 → 子 | props | 子组件定义 props,父组件 :prop="value" |
| 子 → 父 | 自定义事件($emit) | 子组件 this.$emit('event', data),父组件 @event="handle" |
| 兄弟组件 | 事件总线/Vuex/Pinia | 事件总线:Vue.prototype.$bus = new Vue(),$bus.$emit/$on |
| 跨级组件 | provide/inject | 父组件 provide 提供数据,子组件 inject 注入 |
| 任意组件 | Vuex/Pinia | 全局状态管理,直接读取/修改共享数据 |
| 路由传参 | query/params | 跳转路由时携带参数 |
| 本地存储 | localStorage/sessionStorage | 持久化传值(非响应式) |
35. Bootstrap 的原理
Bootstrap 是前端 UI 框架,核心原理:
36. Vue 兄弟组件传值
兄弟组件无直接传值通道,常用 3 种方式:
import Vue from 'vue';
Vue.prototype.$bus = new Vue();
// 2. 组件A发送事件
this.$bus.$emit('sendData', data);
// 3. 组件B接收事件(mounted中)
this.$bus.$on('sendData', (data) => { /* 处理数据 */ });
// 4. 销毁时解绑(避免内存泄漏)
beforeDestroy() {
this.$bus.$off('sendData');
}
37. 如果一个组件需要在多个项目中使用怎么办
核心方案:组件封装并发布为 npm 包,步骤:
38. 简述槽口(Slot)
Slot(插槽)是 Vue 组件的内容分发机制,允许父组件向子组件插入自定义内容:
- 核心类型:
- 默认插槽:子组件 <slot></slot>,父组件直接写内容;
- 具名插槽:子组件 <slot name="header"></slot>,父组件 <template v-slot:header>内容</template>(简写 #header);
- 作用域插槽:子组件向父组件传递数据,父组件自定义渲染逻辑:<!– 子组件 –>
<slot :user="user"></slot>
<!– 父组件 –>
<template v-slot:default="slotProps">
{{ slotProps.user.name }}
</template>
- 作用:提升组件灵活性,实现组件内容的自定义渲染。
39. 简述 watch
watch 是 Vue 的侦听器,用于监听数据变化并执行自定义逻辑:
- 核心特性:
- 监听单个/多个数据(如 data、props、计算属性);
- 支持深度监听(deep: true)、立即执行(immediate: true);
- 可监听对象属性(如 'user.name');
- 示例:<script>
export default {
data() {
return { user: { name: '张三' }, count: 0 };
},
watch: {
// 监听基本类型
count(newVal, oldVal) {
console.log('count变化:', newVal, oldVal);
},
// 监听对象(深度监听)
user: {
handler(newVal) {
console.log('user变化:', newVal);
},
deep: true,
immediate: true // 初始化时执行一次
},
// 监听对象单个属性
'user.name'(newVal) {
console.log('姓名变化:', newVal);
}
}
}
</script>
40. 简述 Vant UI
Vant UI 是有赞开源的移动端 Vue UI 组件库,核心特点:
# 按需引入(需配置babel-plugin-import)
import { Button } from 'vant';
Vue.use(Button);
41. 计算属性与 watch 的区别
| 核心用途 | 派生数据(如 a+b) | 监听数据变化执行副作用(如请求、修改 DOM) |
| 缓存性 | 有缓存,依赖不变则不重新计算 | 无缓存,数据变化即触发 |
| 返回值 | 必须有返回值 | 无需返回值 |
| 语法 | 声明式(类似变量) | 命令式(函数) |
| 适用场景 | 简单的同步数据计算 | 异步操作、复杂的逻辑处理 |
| 深度监听 | 自动深度监听对象属性 | 需手动设置 deep: true |
- 示例对比:// 计算属性:适合简单计算
computed: { fullName() { return this.first + ' ' + this.last; } }
// watch:适合异步逻辑
watch: { firstName(newVal) { this.$axios.get('/api', { params: { name: newVal } }); } }
42. MVVM 框架是什么?它和其他框架的区别是什么?哪些场景适合?
- MVVM 定义:MVVM(Model-View-ViewModel)是前端架构模式,核心是 ViewModel 作为 View 和 Model 的桥梁,实现数据与视图的双向绑定;
- 与其他框架的区别:
- 与 jQuery(无架构):MVVM 数据驱动,无需手动操作 DOM;jQuery 需手动选择 DOM、修改内容;
- 与 React(类 MVVM):React 核心是单向数据流(State→View),需手动 setState 更新;Vue(MVVM)原生支持双向绑定;
- 与 Angular(全量 MVVM):Vue 更轻量、易用,Angular 功能全但学习成本高;
- 适用场景:
- 中大型单页应用(SPA):数据交互频繁,需高效管理状态;
- 表单类应用:双向绑定简化表单处理;
- 移动端/H5 应用:轻量、高性能,适配移动端;
- 不适用场景:简单静态页面(如纯展示页),用 jQuery/原生 JS 更高效。
43. Vue 首屏加载慢的原因,怎么解决的,白屏时间怎么检测,怎么解决白屏问题
(1)首屏加载慢的原因
(2)解决方法
(3)白屏时间检测
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM加载完成时间:', Date.now() – performance.timing.navigationStart);
});
// 监听首屏绘制
new PerformanceObserver((entryList) => {
const entry = entryList.getEntries()[0];
console.log('首屏时间:', entry.startTime);
}).observe({ type: 'paint', buffered: true });
(4)解决白屏问题
44. Vue 双向数据绑定中,怎么实现一侧数据改变之后通知另一侧
核心是发布-订阅模式,分两步:
45. Vuex 流程
Vuex 的核心数据流向是单向循环:
- 简化流程:组件 → Action → Mutation → State → 组件(同步操作可直接 commit Mutation)。
46. Vuex 怎么请求异步数据
Vuex 中异步数据请求需在 Action 中执行,步骤:
// 1. 定义Action
const store = new Vuex.Store({
state: { userList: [] },
mutations: {
SET_USER_LIST(state, data) {
state.userList = data;
}
},
actions: {
// 异步请求数据
async fetchUserList({ commit }) {
try {
const res = await this.$axios.get('/api/user/list');
commit('SET_USER_LIST', res.data); // 提交Mutation修改State
} catch (err) {
console.error('请求失败:', err);
}
}
}
});
// 2. 组件中触发Action
this.$store.dispatch('fetchUserList');
- 注意:Mutation 只能执行同步操作,异步操作必须放在 Action 中。
47. Vuex 中 Action 如何提交给 Mutation
Action 通过 commit 方法提交 Mutation,有两种方式:
increment({ commit }) { // 解构commit
commit('INCREMENT'); // 提交Mutation
}
}
increment(context) {
context.commit('INCREMENT'); // context包含commit/dispatch/state等
}
}
- 带参数提交:commit('INCREMENT', payload)(payload 为任意类型数据)。
48. route 与 router 的区别
| 核心含义 | 当前路由信息对象 | 路由实例(导航控制器) |
| 包含内容 | path、params、query、name 等 | push、replace、go 等导航方法 |
| 用途 | 读取当前路由参数/信息 | 触发路由跳转 |
| 示例 | this.$route.params.id | this.$router.push('/home') |
49. Vuex 有哪几种状态和属性
Vuex 的核心属性(5 个):
50. Vuex 的 state 特性是?
51. Vuex 的 getter 特性是?
52. Vuex 的 mutation 特性是?
53. Vuex 的 action 特性是?
54. Vuex 的优势
55. 简述 Vue 路由懒加载
路由懒加载(按需加载)是代码分割的一种方式,核心是将路由组件拆分为独立的 JS 包,只有访问该路由时才加载对应的包:
- 实现方式:// 基础懒加载
const Home = () => import('./views/Home.vue');
// 带分包命名(webpackChunkName),便于打包后识别
const User = () => import(/* webpackChunkName: "user" */ './views/User.vue');
const routes = [
{ path: '/home', component: Home },
{ path: '/user', component: User }
]; - 优势:
- 减小首屏 JS 包体积,提升首屏加载速度;
- 按需加载,节省带宽和资源;
- 原理:基于 ES6 的动态 import 语法,webpack 打包时自动拆分代码块。
56. v-for 和 v-if 的区别
| 核心用途 | 循环渲染列表 | 条件渲染 DOM |
| 优先级 | 更高(Vue 2) | 更低(Vue 2) |
| 执行时机 | 每次渲染都循环所有数据 | 条件为 true 时才渲染 DOM |
| 性能 | 循环所有数据,性能开销大 | 仅渲染满足条件的 DOM |
| 结合使用 | 不推荐直接结合(Vue 2 中 v-for 优先级高,会先循环再判断,性能差) | 推荐用 computed 过滤数据后再循环 |
- 优化建议:// 错误:v-for和v-if同节点
<div v-for="item in list" v-if="item.visible">{{item.name}}</div>
// 正确:先过滤数据
computed: {
filteredList() {
return this.list.filter(item => item.visible);
}
}
<div v-for="item in filteredList" :key="item.id">{{item.name}}</div> - Vue 3 调整:v-if 优先级高于 v-for,同节点使用会报错,强制开发者先过滤数据。



