Vue3五种父传子通信的方法(超详细带demo)

前言

在 Vue 3 开发中,父子组件通信是最基础、最常用的功能之一。
很多新手可能只知道 props,但实际上 Vue 3 提供了多种方式,适用于不同场景。
本文会详细讲解 5 种父传子通信方式,并附上完整代码示例,帮你彻底掌握!

1. Props(最基础的方式)

1.1 基本用法

父组件通过 props 向子组件传递数据,子组件通过 defineProps 接收。

<!-- 父组件 Parent.vue -->
<template>
  <Child :title="msg" :count="num" />
</template>

<script setup>
import Child from './Child.vue';
const msg = "Vue 3 Props";
const num = 100;
</script>
<!-- 子组件 Child.vue -->
<template>
  <h1>{{ title }}</h1>
  <p>Count: {{ count }}</p>
</template>

<script setup>
const props = defineProps({
  title: String,   // 类型校验
  count: Number,
});
</script>

1.2 Props 高级用法

(1) 默认值 & 必填
defineProps({
  title: {
    type: String,
    required: true,  // 必须传
  },
  count: {
    type: Number,
    default: 0,     // 默认值
  },
});
(2) 复杂类型校验
defineProps({
  user: {
    type: Object,
    default: () => ({ name: 'Guest' }),  // 对象/数组必须用函数返回
  },
  list: {
    type: Array,
    validator: (arr) => arr.length > 0,  // 自定义校验
  },
});

(3) TypeScript 支持
<script setup lang="ts">
interface Props {
  title: string;
  count?: number;  // 可选
}

const props = defineProps<Props>();
</script>
  • interface Props:这是 TypeScript 的语法,用来定义 props 的类型。

  • title: stringtitle 必须是字符串。

  • count?: number? 表示 count 是可选的(可以不传)。

  • defineProps<Props>():用 TypeScript 的方式定义 props。

2. v-model(父子双向绑定)

2.1 基本用法

<!-- 父组件 Parent.vue -->
<template>
  <Child v-model="inputValue" />
  <p>父组件值: {{ inputValue }}</p>
</template>

<script setup>
import { ref } from 'vue';
const inputValue = ref('');
</script>
<!-- 子组件 Child.vue -->
<template>
  <input 
    :value="modelValue" 
    @input="$emit('update:modelValue', $event.target.value)" 
  />
</template>

<script setup>
defineProps(['modelValue']);
defineEmits(['update:modelValue']);
</script>

2.2 多个 v-model

<!-- 父组件 Parent.vue -->
<Child v-model:first="firstName" v-model:last="lastName" />

<!-- 子组件 Child.vue -->
<template>
  <input :value="first" @input="$emit('update:first', $event.target.value)" />
  <input :value="last" @input="$emit('update:last', $event.target.value)" />
</template>

<script setup>
defineProps(['first', 'last']);
defineEmits(['update:first', 'update:last']);
</script>

3. $refs(父调子方法)

3.1 基本用法

<!-- 父组件 Parent.vue -->
<template>
  <Child ref="childRef" />
  <button @click="childRef.sayHello()">调用子组件方法</button>
</template>

<script setup>
import { ref } from 'vue';
const childRef = ref();
</script>
<!-- 子组件 Child.vue -->
<script setup>
function sayHello() {
  alert('Hello from Child!');
}

// 暴露方法给父组件
defineExpose({ sayHello });
</script>

4. Provide / Inject(跨层级通信)

4.1 基本用法

<!-- 父组件 Parent.vue -->
<script setup>
import { provide } from 'vue';
provide('theme', 'dark');  // 提供数据
</script>
<!-- 子组件 Child.vue -->
<script setup>
import { inject } from 'vue';
const theme = inject('theme', 'light');  // 第二个参数是默认值
</script>

4.2 响应式数据

<!-- 父组件 Parent.vue -->
<script setup>
import { provide, ref } from 'vue';
const count = ref(0);
provide('count', count);
</script>

<!-- 子组件 Child.vue -->
<script setup>
import { inject } from 'vue';
const count = inject('count');
</script>

5. Event Bus(全局事件总线)

适用于任意组件通信(Vue 3 推荐使用 mitt 库)。

5.1 安装 mitt

npm install mitt

5.2 使用示例

// eventBus.js
import mitt from 'mitt';
export const eventBus = mitt();
<!-- 父组件 Parent.vue -->
<script setup>
import { eventBus } from './eventBus';
eventBus.emit('update-data', { newData: 123 });
</script>
<!-- 子组件 Child.vue -->
<script setup>
import { eventBus } from './eventBus';
eventBus.on('update-data', (data) => {
  console.log(data);  // { newData: 123 }
});
</script>

总结

方式适用场景特点
props父传子数据支持数据类型验证和默认值
v-model父子双向绑定适用于表单
$refs父调子方法直接操作子组件
provide/inject跨层级传递数据避免props一层层传递
Event Bus任意组件通信全局事件监听

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值