Vue3 组件通信方式的完整版 + Demo 示例代码(保姆级,不完整我倒立喝水)
Vue3组件通信方式完整指南:提供父子、祖孙、跨组件等8种通信方案。核心包括props/emit父子通信、provide/inject祖孙传值、mitt/Pinia跨组件通信、ref/expose父调子方法等。企业级架构分层设计:业务层(组件间通信)、全局状态层(Pinia)、事件总线层(mitt)、浏览器层(多标签页通信)和服务端层(WebSocket)。每种方式配有代码示例,如v-model双
Vue3 组件通信方式的完整版 + Demo 示例代码(保姆级,不完整我倒立喝水)

简单记忆法:
父子 — props + emit
祖孙 — provide / inject
跨组件 — mitt 或 Pinia
全局状态 — Pinia
多标签页 — BroadcastChannel
iframe/跨域 — postMessage
实时通信 — WebSocket
路由通信 — query/params
父调子方法 — ref + expose
🏢 企业级 Vue3 通信方案架构图:
┌───────────────────────────────────────────────┐
│ (业务模块 / 页面) │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 组件 A │───► │ 组件 B │ │
│ │(父 ↔ 子) │◄───│(兄弟组件) │ │
│ └─────────────┘ └─────────────┘ │
│ │ ▲ ▲ │
│ props │ │emit │ provide │
│ ▼ │ │ inject │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 子组件 A1 │ │ 子组件 B1 │ │
│ └─────────────┘ └─────────────┘ │
│ │
│───────────────────────────────────────────────│
│ 全局状态层 │
│ │
│ ┌───────────────────────────────────────┐ │
│ │ Pinia(全局状态) │ │
│ │ 用户信息 / 权限 / 菜单 / 配置 / 缓存 │ │
│ └───────────────────────────────────────┘ │
│ ▲ ▲ │
│ │useStore│ │
│ │ │bus │
│───────────────────────────────────────────────│
│ 全局通信事件层 │
│ │
│ ┌───────────────────────────────────────┐ │
│ │ EventBus(mitt) │ │
│ │ 跨组件无关系通信:消息中心、通知中心 │ │
│ └───────────────────────────────────────┘ │
│ ▲ ▲ │
│───────────────────────────────────────────────│
│ 浏览器层组件通信 │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ BroadcastChannel(多标签页同步) │ │
│ │ LocalStorage event(跨 Tab 通信) │ │
│ │ postMessage(iframe / 跨域通信) │ │
│ └─────────────────────────────────────────┘ │
│───────────────────────────────────────────────│
│ 服务端(实时通信层) │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ WebSocket / SSE │ │
│ │ 实时消息:告警、监控、聊天、业务推送 │ │
│ └─────────────────────────────────────────┘ │
└───────────────────────────────────────────────┘
🚀 1. 父 → 子:Props
最常用方式,父传子数据。
适用场景:静态/响应式数据下发。
Parent.vue
<template>
<Child :title="msg" :count="3" />
</template>
<script setup>
import Child from './Child.vue'
const msg = 'Hello Child'
</script>
Child.vue
<template>
<div>{{ title }} - {{ count }}</div>
</template>
<script setup>
const props = defineProps<{
title: string,
count: number
}>()
</script>
🚀 2. 子 → 父:emit 事件
子组件向父组件发送事件。
适用场景:点击、输入、状态上报。
Parent.vue
<template>
<Child @submit="onSubmit" />
</template>
<script setup>
const onSubmit = (data) => {
console.log('收到子组件数据:', data)
}
</script>
Child.vue
<template>
<button @click="emit('submit', '子组件传来的数据')">提交</button>
</template>
<script setup>
const emit = defineEmits(['submit'])
</script>
🚀 3. v-model(双向绑定)
本质是 props + emit。
适用场景:双向绑定组件。
Parent.vue
<template>
<Child v-model="value" />
<p>父组件值:{{ value }}</p>
</template>
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'
const value = ref('')
</script>
Child.vue
<template>
<input v-model="model" />
</template>
<script setup>
const props = defineProps<{ modelValue: string }>()
const emit = defineEmits(['update:modelValue'])
const model = computed({
get: () => props.modelValue,
set: v => emit('update:modelValue', v)
})
</script>
🚀 4. 插槽(slots)
父向子传递模板内容(UI / DOM)。
适用场景:UI 内容自定义。
Parent.vue
<Child>
<template #header>
<h3>自定义 Header</h3>
</template>
<template #default>
内容插槽
</template>
</Child>
Child.vue
<template>
<header>
<slot name="header" />
</header>
<main>
<slot />
</main>
</template>
🚀 5. ref + defineExpose(父调子方法)
父组件调用子组件方法,子组件显式暴露方法给父组件。
适用场景:弹窗打开、表单校验,大量 UI 组件库使用(如 el-dialog、el-form)。
Parent.vue
<template>
<Child ref="childRef" />
<button @click="childRef?.open()">打开子组件方法</button>
</template>
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'
const childRef = ref()
</script>
Child.vue
<script setup>
const open = () => {
console.log('子组件方法被调用')
}
defineExpose({ open })
</script>
<template>
<div>子组件</div>
</template>
🚀 6. provide / inject(跨层级)
祖先组件向任意后代传值。
适用场景:样式、主题、表单、上下文对象等。
(Vant、Element Plus 广泛使用)
App.vue(祖先)
<script setup>
import { provide } from 'vue'
provide('theme', 'dark')
</script>
<template>
<Parent />
</template>
Child.vue(任意深度)
<script setup>
import { inject } from 'vue'
const theme = inject('theme')
console.log('注入到的值:', theme)
</script>
<template>{{ theme }}</template>
🚀 7. 兄弟组件通信(父中转)
兄弟借助父组件管理状态(最推荐)。
兄弟 A → emit → 父 → props → 兄弟 B
适用场景:最常规兄弟通信方式。
Parent.vue
<template>
<A @change="value = $event" />
<B :value="value" />
</template>
<script setup>
import { ref } from 'vue'
import A from './A.vue'
import B from './B.vue'
const value = ref('')
</script>
A.vue
<script setup>
const emit = defineEmits(['change'])
</script>
<template>
<input @input="emit('change', $event.target.value)" />
</template>
B.vue
<script setup>
const props = defineProps(['value'])
</script>
<template>
<p>来自兄弟 A 的值:{{ value }}</p>
</template>
🚀 8. EventBus(跨组件,解耦,小项目用得多)
一个全局的事件中心。
适用场景:组件很多 / 层级深 / 不想全局状态管理。
bus.ts
import mitt from 'mitt'
export const bus = mitt()
A.vue
<script setup>
import { bus } from './bus'
bus.emit('send', '来自 A 的数据')
</script>
B.vue
<script setup>
import { bus } from './bus'
bus.on('send', (msg) => {
console.log('B 收到数据:', msg)
})
</script>
🚀 9. Pinia(全局状态,推荐)
Vue3 官方状态管理工具。
适用场景:中大型项目的全局状态、用户信息、缓存数据。
store/user.ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({ name: '张三' })
})
任意组件
<script setup>
import { useUserStore } from './store/user'
const user = useUserStore()
console.log(user.name)
</script>
🚀 10. LocalStorage / SessionStorage 通信
持久化通信方式。
适用场景:跨页面通信。
A 页面写入
localStorage.setItem('token', 'abc')
B 页面读取
const token = localStorage.getItem('token')
🚀 11. BroadcastChannel(多标签页通信)
const bc = new BroadcastChannel('app')
bc.postMessage('Hello')
bc.onmessage = (e) => {
console.log('收到:', e.data)
}
🚀 12. window.postMessage(跨 iframe / 页面)
发送:
window.postMessage({ type: 'msg', data: 123 }, '*')
接收:
window.addEventListener('message', (e) => {
console.log(e.data)
})
🚀 13. URL query 传参(跨路由)
适用:页面跳转传参。
发送:
router.push({
path: '/detail',
query: { id: 1 }
})
接收:
const route = useRoute()
console.log(route.query.id)
🚀 14. 路由 params
跳转:
router.push({ name: 'detail', params: { id: 10 } })
接收:
const route = useRoute()
console.log(route.params.id)
🚀 15. WebSocket(实时通信)
组件之间不直接通信,而是依赖后端推送统一数据。
const ws = new WebSocket("ws://xxx")
ws.onmessage = (e) => {
console.log('收到消息:', e.data)
}
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)