Vue 组件通信:5 种常用方式与场景对比
·
Vue 组件通信:5 种常用方式与场景对比
1. Props / $emit
原理:父组件通过 props 向子组件传递数据,子组件通过 $emit 触发事件向父组件传递数据。
代码示例:
<!-- 父组件 -->
<Child :msg="parentMsg" @update="handleUpdate" />
<!-- 子组件 -->
<script>
export default {
props: ['msg'],
methods: {
sendData() {
this.$emit('update', 'new data');
}
}
}
</script>
适用场景:
- ✅ 父子组件直接通信
- ✅ 简单数据流(如表单输入、按钮交互)
缺点: - ❌ 跨层级组件通信繁琐
2. $refs / $parent / $children
原理:直接访问组件实例的属性和方法。
代码示例:
// 父组件调用子组件方法
this.$refs.childComponent.doSomething();
// 子组件调用父组件方法
this.$parent.parentMethod();
适用场景:
- ✅ 需要直接操作组件 DOM 或方法
- ✅ 紧急修复临时需求
缺点: - ❌ 破坏组件封装性
- ❌ 项目重构时易出错
3. Event Bus(事件总线)
原理:创建一个全局 Vue 实例作为事件中心。
代码示例:
// 创建 eventBus.js
import Vue from 'vue';
export const EventBus = new Vue();
// 组件 A(发布事件)
EventBus.$emit('event-name', data);
// 组件 B(监听事件)
EventBus.$on('event-name', (data) => { ... });
适用场景:
- ✅ 任意组件间通信(如兄弟组件)
- ✅ 小型项目快速实现
缺点: - ❌ 事件难以追踪,大型项目易混乱
- ❌ 需手动销毁监听(
beforeDestroy中调用$off)
4. Vuex 状态管理
原理:集中式存储管理所有组件的状态。
代码示例:
// store.js
const store = new Vuex.Store({
state: { count: 0 },
mutations: {
increment(state) { state.count++ }
}
});
// 组件中修改状态
this.$store.commit('increment');
// 组件中读取状态
this.$store.state.count;
适用场景:
- ✅ 中大型项目复杂状态管理
- ✅ 需要状态持久化、调试工具支持
缺点: - ❌ 小型项目过度复杂
- ❌ 学习曲线较陡
5. provide / inject
原理:祖先组件 provide 数据,子孙组件 inject 接收。
代码示例:
// 祖先组件
export default {
provide() {
return { theme: 'dark' };
}
}
// 子孙组件
export default {
inject: ['theme']
}
适用场景:
- ✅ 跨多层级组件传递数据(如主题、配置)
- ✅ 避免逐层传递
props
缺点: - ❌ 数据流向不透明,调试困难
- ❌ 非响应式(需配合
computed实现响应式)
场景对比总结
| 方式 | 适用场景 | 复杂度 | 维护性 |
|---|---|---|---|
Props / $emit |
父子组件简单通信 | ⭐️ | ✅ |
$refs/$parent |
紧急操作组件实例 | ⭐️⭐️ | ❌ |
| Event Bus | 兄弟/任意组件通信(小型项目) | ⭐️⭐️ | ⚠️ |
| Vuex | 中大型项目全局状态管理 | ⭐️⭐️⭐️⭐️ | ✅ |
provide/inject |
跨层级传递配置/主题 | ⭐️⭐️⭐️ | ⚠️ |
最佳实践建议:
- 优先使用 Props /
$emit满足父子通信- 跨组件通信首选 Vuex(中大型项目)或 Event Bus(小型项目)
- 慎用
$refs和$parent,避免耦合- 深层嵌套数据传递可尝试
provide/inject,但需文档明确约定
更多推荐



所有评论(0)