文章目录
一、响应式数据问题
1. 数据更新,视图未更新
- 场景:修改对象或数组后,页面未重新渲染。
- 原因:Vue 无法检测对象属性的直接添加/删除或数组索引的直接修改。
- 解决方案:
// 对象属性 this.$set(this.obj, 'key', value); // 或 Vue.set(this.obj, 'key', value); // 数组索引 this.$set(this.arr, index, value); // 或使用可触发响应的方法(push、splice等) this.arr.splice(index, 1, newValue);
2. 数组监听失效
- 场景:直接通过索引修改数组元素,或修改数组长度。
- 解决方案:
// 正确方式 this.arr = [...this.arr]; // 触发响应 this.arr.splice(0, 1); // 删除第一个元素
二、生命周期与异步问题
3. DOM 操作未生效
- 场景:在
created
生命周期中操作 DOM,元素未渲染。 - 原因:
created
阶段 DOM 尚未挂载。 - 解决方案:
mounted() { // 在此处操作 DOM }
4. 异步数据导致渲染问题
- 场景:组件渲染依赖异步数据,导致初始渲染空白或报错。
- 解决方案:
// 使用 v-if 控制渲染时机 <template v-if="dataLoaded"> <!-- 渲染内容 --> </template>
三、组件通信问题
5. Props 修改警告
- 场景:直接修改子组件中的
props
触发警告。 - 原因:Vue 遵循单向数据流。
- 解决方案:
// 子组件触发事件,由父组件修改 this.$emit('update:propName', newValue); // 父组件使用 .sync 修饰符 <ChildComponent :propName.sync="value" />
6. EventBus 事件重复触发
- 场景:全局事件总线 (
EventBus
) 多次注册导致重复触发。 - 解决方案:
// 在组件销毁前移除监听 beforeDestroy() { EventBus.$off('eventName', this.handler); }
四、路由与导航问题
7. 动态路由参数未更新
- 场景:路由参数变化但组件未重新渲染。
- 原因:Vue 复用组件实例。
- 解决方案:
watch: { '$route.params.id'(newVal) { // 手动刷新数据 this.fetchData(newVal); } } // 或为 router-view 添加 key <router-view :key="$route.fullPath" />
8. 导航守卫未生效
- 场景:全局守卫或组件内守卫未按预期执行。
- 检查点:
- 确保守卫函数中调用
next()
。 - 路由配置中是否正确定义了
meta
字段。
- 确保守卫函数中调用
五、状态管理(Vuex)问题
9. 修改 State 未通过 Mutation
- 场景:直接修改 Vuex 的
state
导致 Devtools 无法追踪。 - 解决方案:
// 严格模式下必须通过 mutation 修改 mutations: { updateState(state, payload) { state.data = payload; } }
10. 异步操作未使用 Action
- 场景:在组件中直接调用异步接口修改 State。
- 解决方案:
// 在 Action 中处理异步逻辑 actions: { async fetchData({ commit }) { const res = await api.getData(); commit('setData', res.data); } }
六、样式与作用域问题
11. Scoped CSS 不生效
- 场景:
<style scoped>
中样式未应用。 - 解决方案:
<!-- 使用深度选择器 --> <style scoped> .parent ::v-deep .child { color: red; } </style>
12. 第三方组件样式覆盖失败
- 场景:无法覆盖 UI 库(如 Element UI)的样式。
- 解决方案:
<!-- 使用全局样式文件(不加 scoped) --> <style> .el-button { margin: 0; } </style>
七、异步与 Promise 问题
13. async/await 导致生命周期错误
- 场景:在
setup
或created
中使用async
导致逻辑混乱。 - 解决方案:
// 在 mounted 中调用异步方法 mounted() { this.loadData(); }, methods: { async loadData() { this.data = await api.getData(); } }
14. 多个异步请求竞态问题
- 场景:快速切换页面时,旧请求覆盖新请求结果。
- 解决方案:
let activeRequest = null; methods: { async fetchData() { if (activeRequest) activeRequest.cancel(); activeRequest = api.getData(); try { this.data = await activeRequest; } catch (error) { // 处理取消逻辑 } } }
八、Vue3 组合式 API 问题
15. 响应式丢失
- 场景:解构
reactive
对象后失去响应性。 - 解决方案:
import { reactive, toRefs } from 'vue'; const state = reactive({ count: 0 }); const { count } = toRefs(state); // 保持响应性
16. watch 监听失效
- 场景:
watch
无法监听到深层次对象变化。 - 解决方案:
watch( () => state.deepObject, (newVal) => { /* 处理逻辑 */ }, { deep: true } );
九、环境与构建问题
17. 开发与生产环境行为不一致
- 场景:开发环境正常,生产环境报错。
- 常见原因:
- 环境变量未正确配置(如
process.env.NODE_ENV
)。 - 未处理静态资源路径(使用
publicPath
配置)。
- 环境变量未正确配置(如
18. Vite 热更新失效
- 场景:修改代码后页面未自动刷新。
- 解决方案:
- 检查是否关闭了 Vite 的 HMR(如手动修改了
index.html
)。 - 确保文件路径大小写正确(某些系统区分大小写)。
- 检查是否关闭了 Vite 的 HMR(如手动修改了
十、其他常见错误
19. v-for 缺少 key
- 场景:控制台警告
Elements in iteration expect to have 'v-bind:key'
。 - 解决方案:
<div v-for="item in list" :key="item.id">{{ item.name }}</div>
20. 方法未定义
- 场景:
[Vue warn]: Method "handleClick" has not been defined
。 - 检查点:
- 方法是否定义在
methods
中。 - 是否存在拼写错误。
- 方法是否定义在
总结
实际开发中,结合浏览器控制台警告、Vue Devtools 调试工具和代码审查,可快速定位并解决问题。