Vue 组件通信方式大全(第7节)

一、props / emits:最基础,也最容易被用坏的"父子直连"🔗

1️⃣ 本质一句话

  • props:父 → 子(数据下发)
  • emits:子 → 父(事件通知)

这是 Vue 官方最推荐、最安全、最清晰的通信方式,没有之一。

2️⃣ 标准用法(别省这两行声明)

vue 复制代码
<!-- Child.vue -->
<script setup>
const props = defineProps({
  count: Number
})

const emit = defineEmits(['update'])
</script>

<template>
  <button @click="emit('update', props.count + 1)">
    +1
  </button>
</template>
vue 复制代码
<!-- Parent.vue -->
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'

const count = ref(0)
</script>

<template>
  <Child :count="count" @update="count = $event" />
</template>

3️⃣ 什么时候必须用 props / emits?

  • 父子组件关系明确
  • 数据流需要可追踪、可调试
  • 想要单向数据流(父是"老板",子只汇报)

🚨 常见翻车现场

  • ❌ 子组件直接改 props
  • ❌ props 当全局状态用
  • ❌ emits 名字随便起(change、handle、xxxEvent 满天飞)

👉 口诀:

父给数据,子不碰;

子要改,喊一声(emit)。


二、provide / inject:跨层通信,但千万别"滥权"🧬

1️⃣ 本质一句话

祖先组件提供(provide),任意后代组件注入(inject)

它解决的是:

👉 中间层不关心,但你又不想层层 props 传递 的问题。

2️⃣ 基本用法

js 复制代码
// Parent.vue
import { provide, ref } from 'vue'

const theme = ref('dark')
provide('theme', theme)
js 复制代码
// DeepChild.vue
import { inject } from 'vue'

const theme = inject('theme')

3️⃣ 使用场景(很重要)

✅ 组件库/基础设施类数据

  • 主题(theme)
  • 国际化(i18n)
  • 表单上下文(Form / FormItem)
  • 当前用户只读信息

🚨 provide / inject 的三大雷区

1️⃣ inject 的数据来源不清晰 (你不知道它从哪来)

2️⃣ 默认不是响应式 (要传 ref / reactive 才行)

3️⃣ 被当成"低配版状态管理"

👉 一句狠话:

provide/inject 是"上下文",不是"仓库"。


三、ref / expose:能用,但要克制的"命令式通信"⚠️

1️⃣ 本质一句话

父组件通过 ref,直接调用子组件方法或访问实例

2️⃣ 标准写法(Vue3 必须 expose)

vue 复制代码
<!-- Child.vue -->
<script setup>
function reset() {
  console.log('reset')
}

defineExpose({ reset })
</script>
vue 复制代码
<!-- Parent.vue -->
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'

const childRef = ref(null)

function handleClick() {
  childRef.value.reset()
}
</script>

<template>
  <Child ref="childRef" />
  <button @click="handleClick">重置子组件</button>
</template>

3️⃣ 适合的场景

✅ 表单校验 / 重置

✅ 弹窗打开 / 关闭

✅ 视频播放控制

✅ 聚焦输入框

🚨 不适合的场景

❌ 数据同步

❌ 状态驱动 UI

❌ 多层组件依赖

👉 记住这句话:

ref/expose 是"遥控器",不是"数据通道"。


四、事件总线:不是不能用,而是"别乱用"📡

1️⃣ 本质一句话

一个全局的事件发布/订阅中心

js 复制代码
// bus.js
import mitt from 'mitt'
export const bus = mitt()
js 复制代码
// A.vue
bus.emit('login', user)
js 复制代码
// B.vue
bus.on('login', (user) => {})

2️⃣ 什么时候还能接受?

✅ 临时工具型功能

  • Toast / Modal / 全局提示
  • 埋点事件
  • 非核心业务

🚨 为什么不推荐?

  • 事件来源不可追踪
  • 容易忘记 off,内存泄漏
  • 事件名冲突
  • 项目一大,灾难级调试体验

👉 真实项目经验:

事件总线一多,迟早会有人问:

"这个事件是谁发的?"

然后,全员沉默 😶


五、状态管理方案对比:什么时候该"上仓库"?📦

1️⃣ 常见方案一览

方案 适合场景
props / emits 父子通信
provide / inject 跨层上下文
ref / expose 命令式控制
事件总线 临时、工具级
Pinia / Vuex 全局业务状态

2️⃣ Pinia 适合什么?

✅ 用户信息

✅ 登录态

✅ 权限

✅ 多页面共享状态

✅ 跨模块通信

js 复制代码
// userStore.ts
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    user: null
  }),
  actions: {
    setUser(u) {
      this.user = u
    }
  }
})
js 复制代码
// 任意组件
const userStore = useUserStore()
userStore.setUser({ name: 'Tom' })

🚨 别什么都丢进状态管理

  • 表单临时状态 ❌
  • UI 展示态 ❌
  • 单组件内部状态 ❌

👉 状态管理是"仓库",不是"垃圾桶"。

六、终极选型指南(直接抄)🧠

✅ 优先级排序(从强烈推荐到谨慎使用)

1️⃣ props / emits (80% 场景)

2️⃣ provide / inject (上下文)

3️⃣ ref / expose (命令式)

4️⃣ 状态管理(Pinia) (全局业务)

5️⃣ 事件总线(能不用就不用)

✅ 一句话决策法

  • 父子关系?👉 props / emits
  • 跨层共享但非业务核心?👉 provide / inject
  • 需要直接调用方法?👉 ref / expose
  • 多页面、多模块共享?👉 Pinia
  • 想偷懒?👉 先冷静一下 😅

结尾反问(送你当文章收尾钩子😏)

组件通信方式从来不是"越高级越好",而是"越清晰越值钱 "。

所以我想反问你一句:
你现在用的通信方式,是在"表达关系",还是在"掩盖混乱"?

相关推荐
专业程序开发源14 分钟前
springboot简历管理系统81389-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·php·课程设计
专业程序开发源28 分钟前
springboot社区养老系统44071-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·php·课程设计
小呆呆66635 分钟前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
凤城老人1 小时前
从 PyQt6 到 Electron:给 Edge TTS 做一个“多角色配音机“的踩坑手记
javascript·typescript·electron
Dovis(誓平步青云)1 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan1 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_2 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
IT_陈寒2 小时前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端
广州华水科技2 小时前
大坝安全监测解决方案:单北斗GNSS形变监测系统应用与维护
前端
星光开发者3 小时前
基于决策树随机森林算法的小说推荐系统的设计与实现-计算机毕设【课程设计】78485
vue.js·算法·微信小程序·django·php·课程设计·express