---
URL: "/zh-CN/blog/2025-07/vue_mitt.html"
LLMS_URL: "/zh-CN/blog/2025-07/vue_mitt.md"
lastUpdated: true
commentabled: true
recommended: true
title: "Vue3 父子组件通信大揭秘：Composition API下的暗号传递艺术"
description: "Vue3 父子组件通信大揭秘：Composition API下的暗号传递艺术"
date:

pageClass: "blog-page-class"
cover: "/covers/vue.svg"
---

---
lastUpdated: true
commentabled: true
recommended: true
title: Vue3 父子组件通信大揭秘：Composition API下的暗号传递艺术
description: Vue3 父子组件通信大揭秘：Composition API下的暗号传递艺术
date: 2025-07-15 14:05:00 
pageClass: blog-page-class
cover: /covers/vue.svg
---

在Vue的世界里，组件就像一群讲究隐私的邻居。父组件想让子组件帮忙做点事（比如“儿子，帮我把房间收拾一下！”），但总不能破门而入吧？这时候就需要一套优雅的“暗号系统”了。Vue3的Composition API给了我们几把钥匙，今天咱们就来玩转这些钥匙，顺便看看为什么有些钥匙是“危险品”！

## 方法一：ref + defineExpose——最推荐的“暗号传递法” ##

### 父组件：给儿子贴个“小纸条”（ref） ###

```vue:Father.vue
<!-- 父组件 -->
<template>
  <ChildComponent ref="childRef" />
  <button @click="callChildMethod">让子组件干活</button>
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const childRef = ref(null); // 准备一个“暗号接收器”

const callChildMethod = () => {
  if (childRef.value) {
    childRef.value.cleanRoom(); // 调用子组件的暗号方法！
  }
};
</script>
```

### 子组件：主动暴露“暗号”（defineExpose） ###

```vue:Child.vue
<!-- 子组件 -->
<script setup>
const cleanRoom = () => {
  console.log("好嘞！正在整理房间～");
  // 这里可以写具体逻辑，比如重置表单、刷新数据等
};

// 暴露暗号！不暴露的话，父组件就是“门外汉”！
defineExpose({
  cleanRoom,
});
</script>
```

### 🌟 关键点： ###

- **defineExpose是Vue3的独门秘籍**：子组件必须主动暴露方法，否则父组件就像对着门说话，没人听。
- **ref是暗号接收器**：父组件通过ref拿到子组件的“门把手”，但只能打开子组件愿意暴露的门缝。

## 方法二：$parent——危险！强行翻墙进入！ ##

```vue:Child.vue
<!-- 子组件尝试调用父组件的方法 -->
<script setup>
const complainToParent = () => {
  if (this.$parent?.parentMethod) {
    this.$parent.parentMethod("房间太乱了！"); // 强行翻墙！
  }
};
</script>
```

### 🚫 为什么不推荐？ ###

- **隐私泄露风险**：子组件直接操作父组件，就像邻居翻你家的墙，万一哪天父组件搬家了，子组件岂不是要迷路？
- **代码难以维护**：父子关系变得像“连体婴”，改一个地方可能牵一发而动全身。

## 方法三：provide/inject——跨楼层喊话（适合远房亲戚） ##

如果子组件是父组件的“远房表亲”（隔了几层组件），可以用 `provide/inject` 传递方法：

```vue:Father.vue
<!-- 父组件 -->
<script setup>
import { provide } from 'vue';

const parentMethod = () => {
  console.log("爸爸收到消息啦！");
};

provide('parentMethod', parentMethod); // 发布暗号
</script>

<!-- 子组件 -->
<script setup>
import { inject } from 'vue';

const parentMethod = inject('parentMethod');

const callParent = () => {
  parentMethod?.("儿子想吃糖！"); // 接收暗号
};
</script>
```

### 📢 使用场景： ###

- **跨层级通信**：当父子相隔太远，`ref` 和 `$parent` 都够不着时，用这个“社区广播站”。
- **但别乱用！**：适合特定场景，频繁使用会让代码像“社区大喇叭”，吵死人！


📊 方法对比：选择你的“暗号系统”

| 方法        |      优点      |  缺点 | 推荐指数 |
| :-----------: | :-----------: | :----: | :----: |
| ref + defineExpose      | 封装性好，父子解耦 | 需主动暴露方法 | ★★★★★ |
| $parent      | 简单粗暴，无需额外配置 | 耦合性高，代码难维护 | ★☆ |
| provide/inject      | 跨层级通信，适合复杂场景 | 可能过度使用，增加理解成本 | ★★★☆ |

## 🚨 注意事项：别让暗号失效！ ##

- **子组件必须暴露方法**：`defineExpose` 是关键，否则父组件调用会报错，就像按了不存在的门铃。
- **防空指针**：父组件调用前检查 `childRef.value` 是否存在，避免 `null` 调用炸出大BUG。
- **别当“暗号贩子”**：只暴露必要方法，保持组件纯洁性。比如子组件的 `privateDiary` 方法，千万别暴露！

## 结语：组件间的友情需要“边界感” ##

Vue3的 `Composition API` 就像一套优雅的社交礼仪，让组件既能互相帮助，又保持恰到好处的距离。记住：**ref + defineExpose是正道**，其他方法是“备选锦囊”。现在，去给你的子组件发个暗号，看看它会不会乖乖干活吧！✨
