vue组件通信有七种方式:一、props单向传值;二、defineemits/$emit子传父事件;三、provide/inject跨层级注入;四、v-model双向绑定语法糖;五、event bus松耦合通信;六、pinia全局状态管理;七、$refs命令式调用子组件。

如果您在开发 Vue 应用时需要让不同组件之间共享数据或响应行为,则必须依赖一套清晰、可控的通信机制。Vue 提供了多种原生与生态方案来应对父子、兄弟、跨级乃至全局状态场景。以下是针对 Vue.js 组件通信方式的系统性展开:
一、Props:父组件向子组件单向传值
Props 是 Vue 中最基础、最符合单向数据流原则的通信方式,用于将父组件的数据以属性形式显式注入子组件,子组件仅可读取不可直接修改。该方式语义明确、调试友好,适用于结构稳定、层级较浅的父子关系。
1、在父组件模板中,使用 v-bind(简写为:)绑定需传递的数据,例如::user-info="currentUser"。
2、在子组件脚本中,通过 defineProps 声明接收的 props,并可指定类型、是否必填及默认值。
3、子组件模板内直接使用 props 定义的变量名,如 {{ userInfo.name }},无需 this 前缀(Composition API 语法糖下)。
二、defineEmits / $emit:子组件向父组件反馈事件
当子组件内部发生用户交互(如按钮点击、表单提交),需通知父组件执行逻辑变更时,应通过事件机制实现反向通信。该方式严格遵循“数据所有权归父组件”原则,避免子组件污染父状态。
1、子组件中调用 defineEmits(['update-user', 'delete-item']) 显式声明可触发的事件名称。
2、在子组件方法中使用 emit('update-user', { id: 1, name: '李四' }) 携带参数派发事件。
3、父组件在引用子组件时,用 @update-user="handleUserUpdate" 监听对应事件并定义处理函数。
三、Provide / Inject:祖先向后代跨层级注入依赖
Provide / Inject 解决的是深层嵌套组件间重复透传 props 的问题,允许祖先组件主动“提供”数据或方法,任意深度的后代组件均可“注入”使用,无需逐层声明 props,适用于主题、配置、工具实例等上下文共享场景。
1、在祖先组件的 setup 函数中,调用 provide('theme', reactive({ mode: 'dark' })) 注入响应式对象。
2、在任意后代组件中,使用 const theme = inject('theme') 获取注入值,支持解构与响应式追踪。
3、若需在注入对象中更新状态,应确保 provide 的值本身是响应式的(如 ref 或 reactive 包裹),否则修改不会触发视图更新。
四、v-model:双向绑定语法糖的底层实现
v-model 并非独立通信方式,而是 Props 与 Events 的组合封装。它简化了表单类组件的受控模式开发,使父子组件间的值同步更接近原生 HTML 行为。Vue 3 中支持多个 v-model 绑定,提升组件复用灵活性。
1、父组件使用
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
2、子组件通过 defineProps({ modelValue: String, filter: String }) 接收绑定值。
3、子组件内部触发 emit('update:modelValue', newValue) 和 emit('update:filter', newFilter) 实现双向同步。
五、Event Bus(自定义事件总线):非父子组件松耦合通信
Event Bus 是一个空的 Vue 实例(Vue 2)或 mitt / tiny-emitter 实例(Vue 3),作为中央事件调度器,使无直接关系的组件可通过统一通道发布与订阅事件,适用于中等复杂度项目中的兄弟组件或跨模块通信。
1、创建独立文件 bus.js,导出 const bus = mitt()(需安装 mitt 库)。
2、发送方组件调用 bus.emit('data-changed', payload) 发布事件。
3、接收方组件在 onMounted 中调用 bus.on('data-changed', handler) 订阅,并在 onUnmounted 中调用 bus.off('data-changed', handler) 清理监听。
六、Pinia:轻量级全局状态管理方案
Pinia 是 Vue 官方推荐的状态管理库,替代 Vuex 成为 Vue 3 项目的首选。它以 store 为单位组织状态,支持 TypeScript、热更新、插件扩展,且 API 极简,适用于中大型应用中多组件共享与持久化状态管理。
1、通过 defineStore('user', { state: () => ({ profile: null }), actions: { fetchProfile() { ... } } }) 创建 store。
2、在任意组件中使用 const userStore = useUserStore() 获取 store 实例。
3、直接访问 userStore.profile 读取状态,调用 userStore.fetchProfile() 触发 action,所有操作自动响应式。
七、$refs:父组件直接调用子组件方法
$refs 提供了一种命令式访问子组件实例的能力,适用于父组件需强制触发子组件特定行为(如表单重置、动画播放)的场景。该方式打破声明式抽象,应谨慎使用,避免过度耦合。
1、在父组件模板中为子组件添加 ref="formRef" 属性。
2、在父组件 setup 中声明 const formRef = ref(null) 并在 onMounted 后确认其存在。
3、调用 formRef.value.resetForm() 执行子组件暴露的 public 方法(需在子组件中通过 defineExpose 显式导出)。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










