VUE3-组件通信

(1)Props ------ 父传子(单向、只读)

是什么 :父组件把数据通过属性传给子组件。子组件通过 props 读取。
什么时候用:父组件要把显示数据或配置传给子组件时(比如标题、初始值、只读配置)。

要点/注意:

  • Props 是 单向(父 → 子),子不能直接修改父传下来的 props(在子里 props 是只读的)。

  • 如果子要"改变"显示值,用本地 ref/computed 拷贝一份,或通过 emit 通知父改变数据(见下)。

  • 在 TypeScript 的 script setup 中用 defineProps<T>() 声明类型(你示例正确)。

示例(父传初始值,子显示):

javascript 复制代码
<!-- 父 -->
<ChildComponent :message="parentMessage" />

<!-- 子 -->
<script setup lang="ts">
interface Props { message: string }
const props = defineProps<Props>()
</script>
<template>
  <div>{{ props.message }}</div>
</template>

快捷提示:如果你需要在子里编辑父的数据,不要直接修改 props,而是 emit 一个事件让父去改。

(2)Emits ------ 子传父(事件机制)

是什么 :子组件用 emit 向父发送事件(带数据),父在模板上通过**@事件名** 监听并处理。
什么时候用:子组件触发行为需要父响应或改变父的数据(例如:子里的按钮点了要通知父更新列表、输入框更新等)。

要点/注意:

  • script setup 里用 const emit = defineEmits<...>() 做类型校验(你的示例也很好)。

  • 事件名在模板里通常用 kebab-case(@update@update-value),在 JS/TS 中可以用 camelCase。

  • 常见约定:父负责数据,子负责 UI/事件 -> "props down, events up"。

示例(子告诉父更新值):

javascript 复制代码
<!-- 子 -->
<script setup lang="ts">
const emit = defineEmits<{ (e: 'update', value: string): void }>()
const handleClick = () => emit('update', 'new value')
</script>

<!-- 父 -->
<ChildComponent @update="handleUpdate" />

v-model 快捷约定 :对表单组件常用 v-model。实现时子接收 modelValue(prop)并 emit update:modelValue 事件:

javascript 复制代码
const props = defineProps<{ modelValue: string }>()
const emit = defineEmits(['update:modelValue'])
// 子在输入时:
emit('update:modelValue', newVal)

(3)Provide / Inject ------ 跨层级传值(祖先 → 后代)

是什么 :祖先组件 provide 一个值,任意深度的后代 inject 获取该值,不需要逐层传 props。
什么时候用:当数据要被很多深层子组件共享,但不想层层透传 props(比如主题、语言、表单上下文、库内部共享状态)。

要点/注意:

  • 默认不是响应式 :如果你 provide('key', 123),之后改变祖先里的普通变量不会自动通知后代。要响应式传递请 provide('k', ref(...) )provide('k', reactive(...))

  • inject 可以带默认值:const theme = inject('theme', 'light')

  • 不要把 provide/inject 当成全局状态管理(复杂逻辑、多个组件频繁读写时用 Pinia/Vuex 更合适)。

示例(响应式主题):

javascript 复制代码
// 祖先
import { ref, provide } from 'vue'
const theme = ref('dark')
provide('theme', theme) // 提供 ref

// 后代
import { inject } from 'vue'
const theme = inject('theme', ref('light')) // theme 是一个 ref,可以直接解构使用

(4)小贴士 & 最佳实践(干货)

  1. 首选规则:Props(向下) + Emits(向上)。这是最清晰的组件边界与职责分配方式。

  2. 不要修改 props :若需要本地编辑,用 const local = ref(props.value)computed({ get: ()=>props.x, set: v => emit('update', v) })

  3. 命名一致性 :事件名用语义化如 save, delete, update:modelValue;props 用清晰名如 items, visible

  4. Provide/Inject 的使用门槛:适合库级别或跨很多层的共享,不适合替代父子通信或做频繁的读写共享(那用 Pinia)。

  5. TypeScriptdefineProps<T>()defineEmits<...>() 能把类型错误在编译时暴露出来,推荐始终加类型。

  6. 事件大小写 :模板中监听事件最好写 kebab-case(@update-value),传递/emit 时在 JS 可写 camelCase。这样兼容模板解析。

相关推荐
EnCi Zheng8 分钟前
M5-markconv自定义CSS样式指南 [特殊字符]
前端·css·python
kyriewen12 分钟前
你的网页慢,用户不说直接走——前端性能监控教你“读心术”
前端·性能优化·监控
广州华水科技13 分钟前
北斗GNSS变形监测在大坝安全监测中的应用与优势分析
前端
前端老石人24 分钟前
前端开发中的 URL 完全指南
开发语言·前端·javascript·css·html
CAE虚拟与现实24 分钟前
五一假期闲来无事,来个前段、后端的说明吧
前端·后端·vtk·three.js·前后端
Sarvartha35 分钟前
三目运算符
linux·服务器·前端
晓晨的博客42 分钟前
ROS1录制的bag包转换为ROS2格式
前端·chrome
Wect1 小时前
LeetCode 72. 编辑距离:动态规划经典题解
前端·算法·typescript
donecoding1 小时前
别再让 pnpm 跟着 nvm 跑了!独立安装终极指南
前端·node.js·前端工程化
不可能的是1 小时前
从 /simplify 指令深挖 Claude Code 多 Agent 协同机制
javascript