Vue3 组件通信的 7 种核心方式与最佳实践(800 字精解)
在 Vue3 组件化开发中,合理的通信方式是架构设计的关键。以下是主要通信方式及其适用场景分析:
<!-- 父组件 -->
<Child :title="msg" @update="handleUpdate"/>
<!-- 子组件 -->
<script setup>
defineProps(['title'])
const emit = defineEmits(['update'])
</script>
特点:单向数据流,符合组件化设计原则
适用:直接父子组件通信
优势:代码清晰可追溯,Vue 官方推荐的基础通信方式
// 祖先组件
provide('globalData', ref(0))
// 后代组件
const data = inject('globalData')
特点:依赖注入机制,支持响应式数据
适用:多层嵌套组件通信
优势:避免逐层传递的繁琐,配合响应式 API 实现高效更新
// store/user.js
export const useUserStore = defineStore('user', {
state: () => ({ name: 'John' })
})
// 组件中使用
const store = useUserStore()
特点:官方推荐状态管理库,支持 Composition API
适用:复杂应用状态共享
优势:类型推断完善,模块化管理,支持热更新
<CustomInput v-model="searchText" />
<!-- 等价于 -->
<CustomInput
:modelValue="searchText"
@update:modelValue="newValue => searchText = newValue"
/>
特点:支持多个 v-model 绑定
适用:表单类组件双向绑定
优势:简化代码结构,提升语义化
<ChildComponent ref="childRef" />
<script setup>
const childRef = ref(null)
// 访问子组件方法
childRef.value.doSomething()
</script>
特点:直接操作组件实例
适用:需要调用子组件方法的场景
注意:需通过 defineExpose 显式暴露方法
// eventBus.js
import mitt from 'mitt'
export const emitter = mitt()
// 组件A
emitter.emit('event', data)
// 组件B
emitter.on('event', handler)
特点:发布订阅模式,完全解耦
适用:非父子组件简单通信
风险:过度使用会导致数据流混乱
// 存储
localStorage.setItem('key', JSON.stringify(data))
// 读取
const data = JSON.parse(localStorage.getItem('key'))
特点:数据持久化存储
适用:需要页面刷新的场景
注意:需处理序列化,非响应式需手动更新
根据项目规模灵活选择:小型项目可用 provide/inject + props 组合,中大型项目必须采用 Pinia 进行状态管理。始终遵循"单向数据流"原则,在保证可维护性的前提下选择最简洁的通信方式。