欢迎光临
我们一直在努力

Vue 组件通信:Vue2 与 Vue3 通用方案解析

Vue 组件通信:Vue2 与 Vue3 通用方案解析

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

一、Vue 组件通信 思维导图

在这里插入图片描述


二、各通信方式 核心关键代码

环境说明

以下代码基于 Vue2 语法(Vue3 组合式API仅语法略有差异,通信逻辑一致),均为单文件组件标准写法。


一、父子组件通信(最常用)

1. 父传子:Props

适用场景:父组件向子组件传递数据、配置项

核心规则:单向数据流,子组件不能直接修改Props

父组件 Parent.vue

<template>
<div>
<!– 动态绑定数据传递给子组件 –>
<Child :msg="parentMsg" :list="parentList" />
</div>
</template>

<script>
import Child from './Child.vue'
export default {
components: { Child },
data() {
return {
parentMsg: '父组件数据',
parentList: [1, 2, 3]
}
}
}
</script>

子组件 Child.vue

<template>
<div>
<p>{{ msg }}</p>
<p>{{ list }}</p>
</div>
</template>

<script>
export default {
// 声明接收props,推荐写法:指定类型/默认值/必填校验
props: {
msg: {
type: String,
required: true
},
list: {
type: Array,
default: () => []
}
}
}
</script>


2. 子传父:自定义事件 $emit

适用场景:子组件向父组件传递数据、通知事件(如点击、表单提交)

子组件 Child.vue

<template>
<button @click="sendData">向父组件传值</button>
</template>

<script>
export default {
methods: {
sendData() {
// 触发自定义事件,传递参数
this.$emit('child-event', '子组件数据', 666)
}
}
}
</script>

父组件 Parent.vue

<template>
<div>
<!– 监听子组件的自定义事件 –>
<Child @child-event="handleChildEvent" />
</div>
</template>

<script>
import Child from './Child.vue'
export default {
components: { Child },
methods: {
// 接收子组件传递的参数
handleChildEvent(data, num) {
console.log(data, num) // 输出:子组件数据 666
}
}
}
</script>


3. 父访问子:ref / $children

适用场景:父组件直接调用子组件方法、获取子组件数据

父组件 Parent.vue

<template>
<div>
<Child ref="childRef" />
<button @click="callChildMethod">调用子组件方法</button>
</div>
</template>

<script>
import Child from './Child.vue'
export default {
components: { Child },
methods: {
callChildMethod() {
// 通过 ref 获取子组件实例
console.log(this.$refs.childRef.childData)
this.$refs.childRef.testMethod()
}
}
}
</script>

子组件 Child.vue

<script>
export default {
data() {
return {
childData: '子组件内部数据'
}
},
methods: {
testMethod() {
alert('子组件方法被调用')
}
}
}
</script>


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

<script>
import Bus from '../utils/bus.js'
export default {
methods: {
sendToBrother() {
Bus.$emit('brother-event', '来自兄弟A的数据')
}
}
}
</script>

3. 接收事件组件 BrotherB.vue

<script>
import Bus from '../utils/bus.js'
export default {
mounted() {
// 监听事件,组件销毁时移除监听
Bus.$on('brother-event', (data) => {
console.log(data)
})
},
beforeDestroy() {
// 解绑事件,避免内存泄漏
Bus.$off('brother-event')
}
}
</script>


三、跨级组件通信(祖孙/多层嵌套)

Provide / Inject 依赖注入

适用场景:多层嵌套组件传值,替代逐层传递Props

顶层组件(祖先)

<script>
export default {
// 提供数据/方法,后代可注入
provide() {
return {
ancestorMsg: '祖先组件数据',
updateMsg: this.updateMsg // 传递方法
}
},
methods: {
updateMsg(val) {
console.log(val)
}
}
}
</script>

底层组件(后代,任意层级)

<script>
export default {
// 注入数据
inject: ['ancestorMsg', 'updateMsg'],
mounted() {
console.log(this.ancestorMsg)
this.updateMsg('后代组件修改数据')
}
}
</script>

注意: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
}
}
})

组件中使用

<script>
import { useUserStore } from '../stores/user'
export default {
setup() {
const userStore = useUserStore()
// 获取数据
console.log(userStore.name)
// 修改数据
userStore.updateName('李四')
}
}
</script>

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 替代零散的事件通信。

  • 赞(0)
    未经允许不得转载:171主机测评 » Vue 组件通信:Vue2 与 Vue3 通用方案解析
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址