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

相关推荐
兆子龙10 分钟前
TypeScript高级类型编程:从入门到精通
前端·后端
SuperEugene12 分钟前
Vue3 模板语法规范实战:v-if/v-for 不混用 + 表达式精简,避坑指南|Vue 组件与模板规范篇
开发语言·前端·javascript·vue.js·前端框架
IT_陈寒18 分钟前
Python开发者的效率革命:这5个技巧让你的代码提速50%!
前端·人工智能·后端
Luna-player19 分钟前
Vue 3 + Vue Router 的路由配置,简单示例
前端·javascript·vue.js
用户693717500138420 分钟前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能
xiaotao13127 分钟前
03. 原子化 CSS 思想
前端·css·tailwind
敲代码的约德尔人30 分钟前
JavaScript 设计模式完全指南
javascript·设计模式
angerdream33 分钟前
最新版vue3+TypeScript开发入门到实战教程之Vue3详解props
javascript·vue.js
小小亮0139 分钟前
qiankun的面试题
前端