Vue3-父子组件通信
2025年12月10日 21:05
在 Vue 3 中,尤其是在使用 `` 并结合 TypeScript 时,父子组件之间的通信变得非常清晰和类型安全。
核心思想是:
- 父组件向子组件 (Prop down): 通过 Props 传递数据。
- 子组件向父组件 (Event up): 通过 Events (自定义事件) 发送消息。
1.父传子
-
定义一些本地数据 (响应式引用
ref)。 -
将这些数据通过
props传递给子组件。 -
监听子组件发出的
emits事件,并定义一个处理函数来更新本地数据。
<div class="parent-container">
<h2>👋 我是父组件</h2>
更新给子组件的消息:
<p>
从子组件收到的消息: <strong>{{ messageFromChild }}</strong>
</p>
<hr/>
</div>
// 1. 导入 ref 用于创建响应式数据
import { ref } from 'vue';
// 2. 导入子组件
import ChildComponent from './ChildComponent.vue';
// 3. 定义父组件的本地状态
const messageForChild = ref('你好,子组件!这是来自父组件的消息。');
const messageFromChild = ref('...等待子组件的消息...'); // 存放从子组件收到的消息
// 4. 定义一个函数,用于处理子组件触发的 'updateMessage' 事件
// TypeScript 在这里可以根据子组件的 emit 定义自动推断 'newMessage' 的类型为 string
const handleChildMessage = (newMessage: string) => {
messageFromChild.value = newMessage;
}
.parent-container {
border: 2px solid #34495e;
background-color: #f0f8ff;
padding: 20px;
border-radius: 8px;
}
input {
margin-left: 10px;
}
2.子接收数据,传递数据给父组件
<div class="child-container">
<h3>👶 我是子组件</h3>
<p>父组件传来的消息 (mainMessage):</p>
<blockquote>{{ props.mainMessage }}</blockquote>
<p>父组件传来的可选数字 (optionalCount):</p>
<blockquote>{{ props.optionalCount || '未提供' }}</blockquote>
向父组件发送消息
</div>
// 1. 接收 Props (父 -> 子)
// 使用泛型参数为 props 定义类型。
// 这是最推荐的 TS 语法。
const props = defineProps<{
mainMessage: string; // 必需的 prop
optionalCount?: number; // 可选的 prop (注意 '?' 符号)
}>()
// 2. 定义 Emits (子 -> 父)
// 使用泛型参数为 emit 定义事件和载荷类型。
const emit = defineEmits<{
// (e: '事件名', 载荷1: 类型, 载荷2: 类型, ...): void
(e: 'updateMessage', message: string): void;
}>()
// 3. 定义一个函数来触发 emit
const sendMessageToParent = () => {
const dataToSend = `你好父组件,我更新了!(时间戳: ${Date.now()})`;
// 4. 触发事件,将数据 (dataToSend) 发送回父组件
// Vue 会查找父组件上绑定的 @updateMessage 监听器
emit('updateMessage', dataToSend);
}
.child-container {
border: 2px dashed #42b983;
background-color: #f0fff4;
padding: 15px;
margin-top: 15px;
border-radius: 8px;
}
blockquote {
margin: 0;
padding: 10px;
background: #fff;
border-left: 5px solid #ccc;
}
3.关键点总结
-
defineProps(子组件用于接收)- 在 `` 中,它是一个宏,无需导入。
- 使用泛型
defineProps<{...}>()来提供最严格的类型检查。 -
props是单向数据流。子组件不应该直接修改props对象中的值。
-
defineEmits(子组件用于发送)- 同样是一个宏,无需导入。
- 使用泛型
defineEmits<{...}>()来定义事件签名。 - 语法
(e: 'eventName', payload: Type): void确保了当你调用emit('eventName', ...)时,payload必须匹配定义的Type。
-
模板中的绑定
- 父组件使用冒号
:(即v-bind) 来传递props。 - 父组件使用艾特
@(即v-on) 来监听emits事件。
- 父组件使用冒号