Vue 组件通信:Vue2 与 Vue3 通用方案解析
Vue 组件通信:Vue2 与 Vue3 通用方案解析
结合 Vue2/Vue3 通用的组件通信场景,我整理了结构化思维导图,并为每种通信方式配套核心关键代码,覆盖开发中高频使用的方案,区分使用场景和适用范围,方便你系统学习和查阅。
一、Vue 组件通信 思维导图

二、各通信方式 核心关键代码
环境说明
以下代码基于 Vue2 语法(Vue3 组合式API仅语法略有差异,通信逻辑一致),均为单文件组件标准写法。
一、父子组件通信(最常用)
1. 父传子:Props
适用场景:父组件向子组件传递数据、配置项
核心规则:单向数据流,子组件不能直接修改Props
父组件 Parent.vue
子组件 Child.vue
{{ msg }}
{{ list }}
2. 子传父:自定义事件 $emit
适用场景:子组件向父组件传递数据、通知事件(如点击、表单提交)
子组件 Child.vue
父组件 Parent.vue
3. 父访问子:ref / $children
适用场景:父组件直接调用子组件方法、获取子组件数据
父组件 Parent.vue
子组件 Child.vue
4. 子访问父:$parent
适用场景:子组件直接访问父组件实例(不推荐频繁使用,耦合度高)
// 子组件中直接调用
this.$parent.parentMethod() // 调用父组件方法
console.log(this.$parent.parentData) // 获取父组件数据
二、兄弟组件通信
方案1:父组件中转(基础方案)
核心逻辑:子1 → 父 → 子2,结合 $emit + Props 实现,代码复用上述父子通信逻辑。
方案2:EventBus 事件总线(全局事件中心)
适用场景:简单项目、无状态管理库时的跨组件通信
1. 创建 bus.js(全局事件对象)
// src/utils/bus.js
import Vue from 'vue'
export default new Vue()
2. 发送事件组件 BrotherA.vue
3. 接收事件组件 BrotherB.vue
三、跨级组件通信(祖孙/多层嵌套)
Provide / Inject 依赖注入
适用场景:多层嵌套组件传值,替代逐层传递Props
顶层组件(祖先)
底层组件(后代,任意层级)
注意:provide/inject 传递的数据非响应式,如需响应式可传递响应式对象或 Vuex/Pinia。
四、全局状态管理(大型项目推荐)
1. Pinia(Vue3 官方推荐)核心代码
定义 store
// src/stores/user.js
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
name: '张三',
age: 18
}),
actions: {
updateName(newName) {
this.name = newName
}
}
})
组件中使用
2. Vuex(Vue2 主流方案)核心代码
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: { count: 0 },
mutations: {
ADD(state) { state.count++ }
},
actions: {
addAsync({ commit }) {
setTimeout(() => commit('ADD'), 1000)
}
}
})
// 组件中使用
this.$store.state.count // 获取数据
this.$store.commit('ADD') // 同步修改
this.$store.dispatch('addAsync') // 异步修改
五、补充通信方案
1. 本地存储通信
适用于跨页面/跨组件持久化数据,核心代码:
// 存储对象
localStorage.setItem('user', JSON.stringify({ name: '测试' }))
// 读取对象
const user = JSON.parse(localStorage.getItem('user'))
2. 路由传参
适用于页面跳转时传递数据
// 1. query 传参(地址栏可见,刷新不丢失)
this.$router.push({ path: '/detail', query: { id: 1 } })
// 接收参数
this.$route.query.id
// 2. params 传参(地址栏不可见,刷新丢失)
this.$router.push({ name: 'Detail', params: { id: 1 } })
// 接收参数
this.$route.params.id
三、方案选型总结
| 通信场景 | 推荐方案 | 备注 |
|---|---|---|
| 父子组件 | Props / $emit | Vue 官方标准方案,优先使用 |
| 兄弟组件 | 父组件中转 / EventBus | 简单项目用EventBus,复杂项目用状态库 |
| 跨级组件 | Provide/Inject | 适合无频繁更新的静态数据 |
| 大型项目全局共享 | Pinia / Vuex | 统一管理状态,便于维护调试 |
| 跨页面持久化 | localStorage | 配合序列化存储复杂数据 |
关键点回顾
-
父子通信是基础,遵循单向数据流,子组件禁止直接修改Props;
-
EventBus 需及时解绑事件,避免内存泄漏;
-
Provide/Inject 适合跨级传值,默认非响应式;
-
大型项目优先使用 Pinia/Vuex 替代零散的事件通信。










