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。这样兼容模板解析。

相关推荐
不会敲代码12 分钟前
解密JavaScript内存机制:从执行上下文到闭包的全景解析
javascript
用户5757303346245 分钟前
🌟 从一行 HTML 到屏幕像素:浏览器是如何“画”出网页的?
前端
NEXT068 分钟前
React Hooks 进阶:useState与useEffect的深度理解
前端·javascript·react.js
sure28214 分钟前
React Native应用中使用sqlite数据库以及音乐应用中的实际应用
前端·react native
CHU72903514 分钟前
扭蛋机盲盒小程序前端功能设计解析:打造趣味与惊喜并存的消费体验
前端·小程序
前端布道师19 分钟前
Web响应式:列表自适应布局
前端
ZeroTaboo21 分钟前
rmx:给 Windows 换一个能用的删除
前端·后端
哈里谢顿21 分钟前
Vue 3 入门完全指南:从零构建你的第一个响应式应用
vue.js
李剑一31 分钟前
Vue实现大屏获取当前所处城市及当地天气(纯免费)
前端
踢足球092942 分钟前
寒假打卡:2026-2-7
java·开发语言·javascript