组件通信
字数: 0 字 时长: 0 分钟
简介
组件通信是 Vue 开发中绕不开的话题,也是面试高频考点。这篇笔记整理了 Vue3 中常用的几种组件通信方式:props/emits、v-model、provide/inject、mitt 事件总线和 Pinia 状态管理。
父子通信:props / emits
父组件通过 props 向子组件传递数据,子组件通过 emits 向父组件触发事件。
vue
<script setup>
import { ref } from "vue";
import Child from "./Child.vue";
const msg = ref("来自父组件的消息");
const handleChange = (val) => {
console.log("子组件说:", val);
};
</script>
<template>
<Child :msg="msg" @change="handleChange" />
</template>vue
<script setup>
// 接收 props
const props = defineProps({
msg: String,
});
// 声明 emits
const emit = defineEmits(["change"]);
const send = () => {
emit("change", "我收到啦");
};
</script>
<template>
<div>{{ props.msg }}</div>
<button @click="send">回复父组件</button>
</template>双向绑定:v-model
v-model 本质是 :modelValue + @update:modelValue 的语法糖,Vue3 支持多个 v-model。
vue
<template>
<!-- 父组件 -->
<Child v-model:title="title" v-model:content="content" />
</template>vue
<script setup>
// 子组件
const props = defineProps(["title", "content"]);
const emit = defineEmits(["update:title", "update:content"]);
emit("update:title", "新标题");
</script>跨层级通信:provide / inject
祖先组件通过 provide 提供数据,后代组件通过 inject 注入使用,适合隔代传值。
js
import { provide, ref } from "vue";
const theme = ref("dark");
provide("theme", theme); // 提供响应式数据js
import { inject } from "vue";
const theme = inject("theme"); // 注入使用注意
provide 提供的数据默认是只读约定,建议在提供方暴露修改方法,避免后代组件直接改动导致数据流向混乱。
任意组件通信:mitt 事件总线
Vue3 移除了 $on、$off,官方推荐使用 mitt 实现事件总线。
bash
pnpm add mittjs
import mitt from "mitt";
export const bus = mitt();js
import { bus } from "./bus";
bus.emit("sayHello", "你好呀");js
import { onUnmounted } from "vue";
import { bus } from "./bus";
const handler = (msg) => console.log(msg);
bus.on("sayHello", handler);
// 组件卸载时记得移除监听
onUnmounted(() => bus.off("sayHello", handler));全局状态管理:Pinia
跨组件共享复杂状态时,直接用 Pinia,它是 Vue 官方推荐的状态管理库,替代了 Vuex。
js
import { defineStore } from "pinia";
export const useUserStore = defineStore("user", {
state: () => ({ name: "卡比", age: 18 }),
getters: {
info: (state) => `${state.name},${state.age} 岁`,
},
actions: {
growUp() {
this.age++;
},
},
});vue
<script setup>
import { useUserStore } from "./stores/user";
const user = useUserStore();
user.growUp(); // 调用 action
</script>
<template>
<div>{{ user.info }}</div>
</template>通信方式选择
| 场景 | 推荐方式 |
|---|---|
| 父传子 | props |
| 子传父 | emits / v-model |
| 跨层级(隔代) | provide / inject |
| 任意组件简单通信 | mitt |
| 全局共享状态 | Pinia |
最后更新于: 2026/8/5 15:00:00