Vue3父子组件通信示例
以下是一个完整的Vue3父子组件通信示例,包含参数传递、事件触发和方法调用:
父组件 ParentComponent.vue
<template> <div class="parent-container"> <h2>父组件</h2> <ChildComponent :title="childTitle" :user-data="user" :item-list="items" @update-title="handleTitleUpdate" @submit-data="handleDataSubmit" ref="childComponentRef" > <template #default> <p>这是插槽内容</p> </template> </ChildComponent> <button @click="callChildMethod">调用子组件方法</button> </div> </template> <script setup> import { ref, reactive } from 'vue' import ChildComponent from './ChildComponent.vue' // 子组件引用(不明白的可以参考 https://www.cnblogs.com/smile-fanyin/p/18772074 ) const childComponentRef = ref(null) // 传递给子组件的props数据 const childTitle = ref('初始标题') const user = reactive({ name: '张三', age: 25, email: 'zhangsan@example.com' }) const items = ref(['苹果', '香蕉', '橙子']) // 处理子组件事件 const handleTitleUpdate = (newTitle) => { console.log('接收到子组件的新标题:', newTitle) childTitle.value = newTitle } const handleDataSubmit = (formData) => { console.log('接收到子组件提交的数据:', formData) // 这里可以处理数据提交逻辑 } // 调用子组件暴露的方法 const callChildMethod = () => { if (childComponentRef.value) { childComponentRef.value.resetForm() } } </script> <style scoped> .parent-container { padding: 20px; border: 2px solid #3498db; margin: 20px; } </style>
子组件 ChildComponent.vue
<template> <div class="child-container"> <h3>子组件 - {{ title }}</h3> <!-- 显示props数据 --> <p>用户信息:{{ userData.name }} ({{ userData.age }})</p> <ul> <li v-for="(item, index) in itemList" :key="index"> {{ item }} </li> </ul> <!-- 表单示例 --> <form @submit.prevent="submitForm"> <input v-model="localTitle" type="text"> <button type="submit">更新标题</button> </form> <!-- 插槽 --> <slot></slot> </div> </template> <script setup> import { ref, defineProps, defineEmits, watch } from 'vue' // 定义props const props = defineProps({ title: { type: String, default: '默认标题' }, userData: { type: Object, default: () => ({}) }, itemList: { type: Array, default: () => [] } }) // 定义事件 const emit = defineEmits(['update-title', 'submit-data']) // 本地数据 const localTitle = ref(props.title) // 监听props变化 watch(() => props.title, (newVal) => { localTitle.value = newVal }) // 表单提交方法 const submitForm = () => { emit('update-title', localTitle.value) emit('submit-data', { newTitle: localTitle.value, timestamp: new Date().toISOString() }) } // 暴露给父组件的方法 const resetForm = () => { localTitle.value = props.title console.log('表单已重置') } // 暴露方法 defineExpose({ resetForm }) </script> <style scoped> .child-container { padding: 15px; border: 1px solid #e74c3c; margin: 10px 0; } input { margin: 10px; padding: 5px; } </style>
主要通信方式说明:
-
Props 传参:
-
父组件通过
:propName="value"传递数据 -
子组件使用
defineProps接收 -
支持类型检查、默认值和复杂对象
-
-
自定义事件:
-
子组件通过
defineEmits定义事件 -
使用
emit('eventName', payload)触发事件 -
父组件通过
@eventName="handler"监听
-
-
组件引用:
-
父组件使用
ref获取子组件实例 -
子组件通过
defineExpose暴露方法 -
父组件可以调用子组件暴露的方法
-
-
双向绑定:
-
可以通过
v-model实现(Vue3支持多个v-model) -
或通过 props + 事件组合实现
-
-
插槽通信:
-
父组件通过
<template #slotName>传递内容 -
子组件通过
<slot>接收内容
-
使用场景示例:
-
父组件传递初始配置数据(props)
-
子组件提交表单数据(自定义事件)
-
父组件重置子组件状态(暴露方法)
-
动态更新标题(双向数据流)
-
内容定制(插槽)
注意事项:
-
始终使用
defineProps和defineEmits进行类型定义 -
复杂对象的默认值应该使用工厂函数返回
-
避免直接修改props,使用本地数据副本
-
事件命名建议使用kebab-case(update-title)
-
暴露方法时注意组件封装性,只暴露必要接口
这个示例展示了Vue3中最常用的父子组件通信方式,可以根据具体需求组合使用这些方法来实现各种组件交互场景。

浙公网安备 33010602011771号