共计 1976 个字符,预计需要花费 5 分钟才能阅读完成。
痛点分析:新手常踩的组件通信坑
刚接触 Vue2 时,我最头疼的就是组件间的数据传递。比如一个商品列表页需要同步购物车数量,最初的做法是把所有状态都放在父组件,然后层层传递 props。这样会导致:

- 组件像俄罗斯套娃一样嵌套,修改一个数据要穿透好几层
- 兄弟组件间通信必须通过共同的父组件中转
- 代码里到处都是
this.$parent.$parent这种脆弱引用
更糟的是,有些同学直接用 this.$refs.child.data=value 暴力修改子组件数据,这种反向操作会让数据流变得难以追踪。
三大方案横向对比
1. Props/$emit
- 优点:官方推荐、父子组件显式通信、类型检查支持
- 缺点:跨级组件需层层传递、兄弟组件通信繁琐
2. Event Bus
- 优点:任意组件间通信、轻量级实现
- 缺点:事件名全局污染、难以调试、需手动销毁
3. Vuex
- 优点:集中式状态管理、时间旅行调试、严格的数据流
- 缺点:学习成本高、小型项目可能过度设计
实战演示
Props 与自定义事件
<!-- Father.vue -->
<template>
<Child
:count="parentCount"
@update="handleUpdate"
/>
</template>
<script>
export default {data() {return { parentCount: 0}
},
methods: {handleUpdate(newVal) {this.parentCount = newVal}
}
}
</script>
<!-- Child.vue -->
<template>
<button @click="$emit('update', count + 1)">
点击 +1 (当前: {{ count}})
</button>
</template>
<script>
export default {
props: {count: { type: Number, default: 0}
}
}
</script>
Event Bus 完整实现
// eventBus.js
import Vue from 'vue'
export default new Vue()
// 组件 A(发送事件)import bus from './eventBus'
bus.$emit('global-event', { data: 123})
// 组件 B(接收事件)created() {bus.$on('global-event', this.handleEvent)
},
beforeDestroy() {bus.$off('global-event', this.handleEvent) // 必须销毁!},
methods: {handleEvent(payload) {console.log(payload.data)
}
}
Vuex 数据流图解
┌─────────┐ ┌─────────────┐ ┌─────────┐
│ 组件 │ → │ dispatch │ → │ actions │
└─────────┘ └─────────────┘ └─────────┘
↓
┌─────────┐ ┌─────────────┐ ┌─────────┐
│ state │ ← │ commit │ ← │ mutations│
└─────────┘ └─────────────┘ └─────────┘
避坑指南
避免直接修改 props
错误做法:
props: ['list'],
methods: {removeItem(index) {this.list.splice(index, 1) // 直接修改 props!}
}
正确做法:
// 子组件触发事件
this.$emit('update-list', newList)
// 父组件处理
<Child :list="dataList" @update-list="dataList = $event" />
Vuex 模块化分割
- 按功能划分模块(如 user、cart 模块)
- 每个模块包含自己的 state/mutations/actions
- 命名空间开启
namespaced: true - 通过
mapState/mapActions辅助函数访问
性能考量
用 Chrome Performance 录制对比:
– 纯 props 传参:组件树越深性能下降越明显
– Event Bus:事件监听过多会导致内存泄漏
– Vuex:首次加载稍慢,但大数据量下更新效率更高
代码规范建议
- 自定义事件名使用 kebab-case(如
update-list) - Prop 定义尽量写完整对象形式(包含 type 和 default)
- Vuex 的 mutation 类型用常量命名(如
SET_USER_INFO) - 超过 3 个 props 时考虑使用对象传参
延伸思考
当项目出现以下特征时,就该考虑上 Vuex 了:
– 多个视图依赖同一状态
– 来自不同视图的行为需要变更同一状态
– 组件层级超过 3 层且需要跨级通信
但切记:不要为了用 Vuex 而用 Vuex,简单的父子通信用 props 才是最佳实践。
正文完
