Vue3实现组件通信的14种方式详解与实战

 更新时间:2025年08月12日 09:36:08   作者:编程随想_Code  
在Vue3中,组件通信仍然是一个非常重要的话题,因为在大多数应用程序中,不同的组件之间需要进行数据传递和交互,在Vue3中,组件通信有多种方式可供选择,本文给大家介绍了Vue3实现组件通信的14种方式,需要的朋友可以参考下

一、父子组件通信

1. props 父传子

适用场景:父组件向子组件传递数据
核心用法defineProps 接收 props

<!-- 父组件 Parent.vue -->
<template>
  <Child :message="parentMsg" />
</template>
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';

const parentMsg = ref('Hello from Parent');
</script>

<!-- 子组件 Child.vue -->
<template>
  <div>父组件传递的props: {{ message }}</div>
</template>
<script setup>
const props = defineProps({
  message: String
});
</script>

注意事项

  • 保持单向数据流,子组件不要直接修改 props。
  • 可通过 defineProps 设置类型校验和默认值。

2. defineEmits 子传父

适用场景:子组件向父组件传递数据
核心用法defineEmits 定义自定义事件

<!-- 子组件 Child.vue -->
<template>
  <button @click="sendData">发送数据</button>
</template>
<script setup>
const emit = defineEmits(['update']);
function sendData() {
  emit('update', 'Data from Child');
}
</script>

<!-- 父组件 Parent.vue -->
<template>
  <Child @update="handleUpdate" />
</template>
<script setup>
function handleUpdate(data) {
  console.log('接收到子组件数据:', data);
}
</script>

补充

  • 推荐使用 update:propName 命名规范(如 update:count)。
  • 避免直接传递父组件方法给子组件调用(如 <Child :onUpdate="handleUpdate" />)。

3. $attrs 属性透传

适用场景:透传未声明的属性到子组件
核心用法$attrs 自动继承父组件未声明的属性

<!-- 父组件 Parent.vue -->
<template>
  <Child :customAttr="123" />
</template>

<!-- 子组件 Child.vue -->
<template>
  <div v-attrs="$attrs"></div>
</template>
<script setup>
import { useAttrs } from 'vue';
const attrs = useAttrs();
console.log(attrs.customAttr); // 输出 123
</script>

4. ref + defineExpose

适用场景:父组件调用子组件方法或访问子组件数据
核心用法ref 获取子组件实例,defineExpose 暴露方法/数据

<!-- 父组件 Parent.vue -->
<template>
  <Child ref="childRef" />
  <button @click="callChildMethod">调用子组件方法</button>
</template>
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';

const childRef = ref(null);
function callChildMethod() {
  childRef.value?.childMethod();
}
</script>

<!-- 子组件 Child.vue -->
<script setup>
function childMethod() {
  console.log('子组件方法被调用');
}
defineExpose({ childMethod });
</script>

注意事项

  • 仅在必要时使用(如表单验证),避免过度依赖。

5. v-model 双向绑定

适用场景:实现父子组件双向数据绑定
核心用法modelValue + update:modelValue

<!-- 父组件 Parent.vue -->
<template>
  <Child v-model="value" />
</template>
<script setup>
import { ref } from 'vue';
const value = ref('初始值');
</script>

<!-- 子组件 Child.vue -->
<template>
  <input :value="modelValue" @input="updateValue" />
</template>
<script setup>
const props = defineProps(['modelValue']);
const emit = defineEmits(['update:modelValue']);
function updateValue(e) {
  emit('update:modelValue', e.target.value);
}
</script>

二、兄弟组件通信

6. 父组件中转

适用场景:兄弟组件通过父组件共享数据

<!-- 父组件 Parent.vue -->
<template>
  <BrotherA @data-change="handleDataChange" />
  <BrotherB :shared-data="sharedData" />
</template>
<script setup>
import { ref } from 'vue';
const sharedData = ref('');
function handleDataChange(data) {
  sharedData.value = data;
}
</script>

7. mitt 事件总线

适用场景:轻量级解耦通信(无共同父组件)
核心用法mitt 创建事件中心

// eventBus.js
import mitt from 'mitt';
export const emitter = mitt();

// 组件A
<script setup>
import { emitter } from './eventBus.js';
function sendData() {
  emitter.emit('brother-event', { id: 1 });
}
</script>

// 组件B
<script setup>
import { emitter } from './eventBus.js';
emitter.on('brother-event', (data) => {
  console.log('接收到数据:', data);
});
</script>

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

适用场景:复杂应用中的全局状态共享

// store/counter.js (Pinia)
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  actions: { increment() { this.count++; } }
});

// 组件A
<script setup>
import { useCounterStore } from '@/store/counter';
const store = useCounterStore();
store.increment();
</script>

// 组件B
<script setup>
import { useCounterStore } from '@/store/counter';
const store = useCounterStore();
console.log(store.count);
</script>

三、跨层级通信

9. provide/inject

适用场景:祖孙组件或深层嵌套组件通信

<!-- 父组件 Parent.vue -->
<script setup>
import { provide, ref } from 'vue';
const theme = ref('dark');
provide('theme', theme);
</script>

<!-- 子组件 Child.vue -->
<script setup>
import { inject } from 'vue';
const theme = inject('theme');
console.log('当前主题:', theme.value);
</script>

10. 全局状态管理(Pinia/Vuex)

与兄弟组件通信中的 Pinia 用法一致,适用于跨层级状态共享。

四、其他通信方式

11. 浏览器本地存储(localStorage/sessionStorage)

适用场景:持久化数据共享(如用户偏好设置)

// 存储数据
localStorage.setItem('user', JSON.stringify({ name: '豆豆' }));

// 读取数据
const user = JSON.parse(localStorage.getItem('user'));
console.log(user.name); // 输出 豆豆

12. 全局 window 对象

适用场景:临时跨组件通信(慎用)

12. 全局 window 对象
适用场景:临时跨组件通信(慎用)

13. ES6 模块化(import/export)

适用场景:常量或工具函数共享

// constants.js
export const API_URL = 'https://api.example.com';

// 组件中使用
import { API_URL } from '@/constants';
console.log(API_URL); // 输出 https://api.example.com

14. 作用域插槽(Slot Props)

适用场景:父组件向子组件传递函数或配置对象

<!-- 父组件 Parent.vue -->
<template>
  <Child>
    <template #default="{ config }">
      <div :style="config">{{ config.title }}</div>
    </template>
  </Child>
</template>

<!-- 子组件 Child.vue -->
<script setup>
import { reactive } from 'vue';
const config = reactive({ title: 'Slot Injected Config' });
</script>

五、最佳实践建议

优先选择标准化方案

80% 场景使用 props + emits

复杂场景选择 provide/inject 或状态管理库。

避免过度使用全局状态

仅当数据需要在多组件间共享时使用 Pinia/Vuex。

善用 $attrs

减少子组件 props 定义,实现属性透传。

谨慎操作 ref

仅在必要时直接调用子组件方法,保持组件解耦。

事件命名规范

使用 on[EventName] 格式,如 on:update

六、总结

Vue3 提供了丰富且灵活的组件通信方式,开发者应根据具体场景选择最优方案。以下是常见场景的推荐选择:

场景推荐通信方式
父子通信props + defineEmits
兄弟组件通信mitt 或父组件中转
跨层级通信provide/inject 或 Pinia
全局状态共享Pinia 或 Vuex
临时数据共享localStorage 或 window

掌握这些通信方式后,可以更高效地构建复杂应用。建议将示例代码复制到项目中运行,观察不同方式的数据流向和效果差异。

以上就是Vue3实现组件通信的14种方式详解与实战的详细内容,更多关于Vue3组件通信方式的资料请关注脚本之家其它相关文章!

相关文章

  • vue3 defineExpose的使用及应用场景分析

    vue3 defineExpose的使用及应用场景分析

    Vue3中defineExpose用于向父组件暴露子组件的属性和方法,尤其在script setup语法中,需显式声明以实现组件间交互,可控制暴露内容,避免过度暴露,同时注意响应式数据解包与测试影响,本文给大家介绍vue3 defineExpose的使用,感兴趣的朋友一起看看吧
    2025-06-06
  • vue组件watch属性实例讲解

    vue组件watch属性实例讲解

    这篇文章主要为大家详细介绍了vue组件watch属性实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • Vue cli+mui 区域滚动的实例代码

    Vue cli+mui 区域滚动的实例代码

    下面小编就为大家分享一篇Vue cli+mui 区域滚动的实例代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • Vue组件库发布到npm详解

    Vue组件库发布到npm详解

    本片文章给大家详细介绍了如何将Vue组件库发布到npm的方法以及代码示例分享,感兴趣的朋友参考学习下。
    2018-02-02
  • elementui弹窗页按钮重复提交问题解决方法

    elementui弹窗页按钮重复提交问题解决方法

    本文主要介绍了elementui弹窗页按钮重复提交问题解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-08-08
  • vue3实现高德地图天气小组件

    vue3实现高德地图天气小组件

    这篇文章主要为大家详细介绍了如何使用vue3实现一个高德地图天气小组件,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-10-10
  • vue中字符串如何拼接路由path路径

    vue中字符串如何拼接路由path路径

    这篇文章主要介绍了vue中字符串如何拼接路由path路径方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Vue前端解析Excel数据方式

    Vue前端解析Excel数据方式

    这篇文章主要介绍了Vue前端解析Excel数据方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • Vue中的前端crypto.js加解密

    Vue中的前端crypto.js加解密

    这篇文章主要介绍了Vue中的前端crypto.js加解密问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • 解决Vue3.0刷新页面警告[Vue Router warn]:No match found for location with path /xxx

    解决Vue3.0刷新页面警告[Vue Router warn]:No match 

    这篇文章主要介绍了解决Vue3.0刷新页面警告[Vue Router warn]:No match found for location with path /xxx问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03

最新评论