一文读懂 Vue 组件间通信机制(含 Vue2 / Vue3 区别)

一、组件间通信的概念

在 Vue 中,组件(Component) 是最核心的概念之一。每个 .vue 文件都可以视为一个独立的组件。

通信(Communication) 是指一个组件如何将信息传递给另一个组件。

通俗地说:

组件间通信,就是不同组件之间如何共享数据、触发行为、进行信息交互的过程。

例如:当我们使用 UI 框架中的 table 组件时,需要向它传入 data 数据,这个"传值"的过程本质上就是一种组件通信。


二、组件间通信解决了什么问题?

在实际开发中,每个组件都有自己的作用域,数据默认是相互隔离的。但我们经常希望:

  • 父组件能把数据传给子组件;
  • 子组件能向父组件反馈事件或数据;
  • 两个兄弟组件能共享状态;
  • 甚至是跨层级(祖孙、非亲缘)组件之间的数据共享。

这正是组件通信的意义所在

让组件之间能够协作、共享数据,从而构成一个有机、完整的应用系统。


三、组件间通信的分类

按照组件关系,通信可分为以下几种:

  1. 父子组件通信
  2. 兄弟组件通信
  3. 祖孙组件通信
  4. 非关系组件通信

简单关系图如下:

css 复制代码
Parent
 ├── Child A
 └── Child B
      └── GrandChild

四、Vue 中 8 种常见通信方案

下面是 Vue2 / Vue3 通用的 8 种通信方式,并在最后补充两者的区别。


1. props 传递数据(父 → 子)

适用场景: 父组件向子组件传值。

子组件定义:

yaml 复制代码
export default {
  props: {
    name: String,
    age: {
      type: Number,
      default: 18,
      required: true
    }
  }
}

父组件使用:

ini 复制代码
<Child name="Jack" :age="18" />

📘 Vue3 区别:

Vue3 支持在 <script setup> 中使用 defineProps

javascript 复制代码
const props = defineProps({
  name: String,
  age: Number
})

2. $emit 触发自定义事件(子 → 父)

适用场景: 子组件向父组件传递数据或事件。

子组件:

kotlin 复制代码
this.$emit('add', good)

父组件:

ini 复制代码
<Child @add="cartAdd($event)" />

📘 Vue3 区别:

Vue3 使用 defineEmits

scss 复制代码
const emit = defineEmits(['add'])
emit('add', good)

3. ref 获取子组件实例(父 → 子)

适用场景: 父组件想直接访问子组件实例或方法。

父组件:

ini 复制代码
<Child ref="foo" />
kotlin 复制代码
this.$refs.foo.someMethod()

📘 Vue3 区别:

Vue3 的 ref 通过 setup 中的 ref() 引用,访问方式为 childRef.value


4. EventBus 事件总线(兄弟组件)

适用场景: 兄弟组件之间传值。

Bus.js:

javascript 复制代码
import Vue from 'vue'
export const Bus = new Vue()

发送方:

bash 复制代码
Bus.$emit('foo', data)

接收方:

javascript 复制代码
Bus.$on('foo', (data) => { console.log(data) })

📘 Vue3 区别:

Vue3 没有 $on/$off,可用第三方库(如 mitt)实现轻量事件总线:

javascript 复制代码
import mitt from 'mitt'
export const bus = mitt()

bus.emit('foo', data)
bus.on('foo', handler)

5. <math xmlns="http://www.w3.org/1998/Math/MathML"> p a r e n t / parent / </math>parent/root(祖辈 → 后代)

适用场景: 通过组件实例树访问父组件或根组件方法。

kotlin 复制代码
this.$parent.someMethod()
this.$root.globalFn()

📘 Vue3 区别:

仍可用,但在 Composition API 下不推荐,应优先使用 provide/inject


6. <math xmlns="http://www.w3.org/1998/Math/MathML"> a t t r s 与 attrs 与 </math>attrs与listeners(祖先 → 子孙)

适用场景: 批量向下传递属性与事件。

xml 复制代码
<!-- Parent.vue -->
<Child2 msg="hello" @some-event="handleEvent" />

<!-- Child2.vue -->
<Grandson v-bind="$attrs" v-on="$listeners" />

<!-- Grandson.vue -->
<div @click="$emit('some-event', 'from grandson')">
  {{ msg }}
</div>

📘 Vue3 区别:

Vue3 将 $listeners 合并入 $attrs,事件监听器自动包含其中:

ini 复制代码
<Grandson v-bind="$attrs" />

7. Provide / Inject(祖孙通信)

适用场景: 祖先组件向任意深度的后代组件传递数据。

祖先组件:

javascript 复制代码
provide() {
  return {
    foo: 'foo'
  }
}

后代组件:

vbnet 复制代码
inject: ['foo']

📘 Vue3 区别:

Vue3 使用 Composition API:

javascript 复制代码
// 祖先
import { provide } from 'vue'
provide('foo', 'foo')

// 后代
import { inject } from 'vue'
const foo = inject('foo')

8. Vuex(或 Pinia)(全局状态管理)

适用场景: 复杂组件关系、跨层级状态共享。

Vuex 核心概念:

  • state:存放共享状态;
  • getters:相当于计算属性;
  • mutations:同步修改 state;
  • actions:支持异步逻辑;
  • modules:模块化管理。

📘 Vue3 推荐:

Vue 官方推荐使用 Pinia,API 更简洁、类型友好。


五、通信方式选择建议

关系类型 推荐通信方式 说明
父 → 子 props 简单直接
子 → 父 $emit 常用于回调
父 ↔ 子 ref 调用方法或取值
兄弟组件 EventBus / mitt 中央事件总线
祖孙组件 provide / inject 优雅高效
非关系组件 Vuex / Pinia 全局状态共享
属性透传 $attrs / $listeners 批量下传属性
简单共享状态 Composition API + reactive() Vue3 场景

六、小结

  • 父子通信: 使用 props$emit 最简洁,也可用 ref
  • 兄弟通信: 推荐 EventBusmitt
  • 祖孙通信:provide / inject 最优雅。
  • 全局通信: 使用 Vuex(Vue2)或 Pinia(Vue3)。
  • Vue3 提升点: Composition API 让通信更灵活,逻辑更集中。

总结一句话:

在 Vue 中,组件间通信的本质就是------让数据在不同组件间可控地流动


本文内容由人工智能生成,仅供学习与参考使用,请在实际应用中结合自身情况进行判断。

相关推荐
weixin_462446232 小时前
nodejs 下使用 Prettier 美化单个 JS 文件(完整教程)
开发语言·javascript·ecmascript
岭子笑笑3 小时前
vant 4 之loading组件源码阅读
前端
q_19132846953 小时前
基于SpringBoot2+Vue2的行业知识答题考试系统
java·vue.js·spring boot·mysql·毕业设计·计算机毕业设计·演示文稿
hxmmm3 小时前
自定义封装 vue多页项目新增项目脚手架
前端·javascript·node.js
ETA83 小时前
JS执行机制揭秘:你以为的“顺序执行”,其实是V8引擎在背后搞事情!
前端·javascript
鹏北海-RemHusband3 小时前
微前端实现方式:HTML Entry 与 JS Entry 的区别
前端·javascript·html
行走的陀螺仪3 小时前
JavaScript 装饰器完全指南(原理/分类/场景/实战/兼容)
开发语言·javascript·ecmascript·装饰器
瘦的可以下饭了3 小时前
3 链表 二叉树
前端·javascript
我那工具都齐_明早我过来上班3 小时前
WebODM生成3DTiles模型在Cesium地图上会垂直显示问题解决(y-up-to-z-up)
前端·gis
粉末的沉淀3 小时前
jeecgboot:electron桌面应用打包
前端·javascript·electron