zzz 发表于 2025-9-2 16:24:35

vue3父子组件通信常用方法

本帖最后由 zzz 于 2025-9-2 16:34 编辑

1. Props (父传子)
父组件通过属性(Attributes)的方式将数据传递给子组件。
<script setup>
// 1. 接收父组件传递的 props
const props = defineProps({
title: String,
count: {
type: Number,
default: 0
}
});
</script>
<template>
<div>
<h2>{{ title }}</h2>
<p>Count: {{ count }}</p>
</div>
</template>//父组件 (Parent.vue):通过 v-bind: (或缩写 :) 动态传递数据。
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const parentCount = ref(10);
const parentTitle = ref('Hello from Parent');
</script>
<template>
<div>
<!-- 2. 传递 props -->
<Child :title="parentTitle" :count="parentCount" />
</div>
</template>特性:
1.单向数据流:数据只能从父组件流向子组件(知道数据从哪里来,为何变化)。
2.强类型/验证:可以详细定义每个 Prop 的类型、默认值、必要性及自定义验证器。2. 自定义事件 (子传父)
子组件通过触发($emit)自定义事件,父组件通过监听(v-on)该事件来接收数据或执行操作。
//子组件 (Child.vue):使用 defineEmits 来声明要触发的事件。
<script setup>
// 1. 声明要触发的事件
const emit = defineEmits(['updateCount', 'reset']);
const handleClick = () => {
// 2. 触发事件,并传递数据
emit('updateCount', 5); // 传递一个数值
};
const reset = () => {
emit('reset'); // 触发事件,可以不传递数据
};
</script>
<template>
<button @click="handleClick">Add 5</button>
<button @click="reset">Reset</button>
</template>//父组件 (Parent.vue):使用 v-on: (或缩写 @)来监听子组件触发的事件。
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const count = ref(0);
// 3. 定义事件处理函数,接收子组件传递的数据
const handleUpdate = (increment) => {
count.value += increment;
};
const handleReset = () => {
count.value = 0;
};
</script>
<template>
<div>
<p>Parent Count: {{ count }}</p>
<!-- 监听子组件触发的事件 -->
<Child @update-count="handleUpdate" @reset="handleReset" />
</div>
</template>特性:
1.是子组件向父组件通信的核心方式。
2.事件名可以使用 kebab-case(update-count)或 camelCase(updateCount),但在模板中建议使用 kebab-case。3. v-model (双向绑定)
v-model 是 props 和 自定义事件 的组合语法糖,用于实现父子组件数据的双向绑定。//子组件 (Child.vue)
<script setup>
// 1. 使用 defineModel 宏
// 它声明了一个 modelValue prop 和一个 update:modelValue 事件
const model = defineModel();
const updateValue = (newValue) => {
model.value = newValue; // 直接赋值,会自动触发更新
};
</script>
<template>
<input :value="model" @input="updateValue($event.target.value)" />
</template>//父组件 (Parent.vue)
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const message = ref('Hello');
</script>
<template>
<!-- 2. 使用 v-model 进行双向绑定 -->
<Child v-model="message" />
<p>Parent bound value: {{ message }}</p>
</template>//多个 v-model 绑定:可以使用 defineModel('modelName') 为多个属性创建双向绑定。
// Child.vue
const title = defineModel('title');
const visible = defineModel('visible');
// Parent.vue
<Child v-model:title="pageTitle" v-model:visible="isVisible" />4. 模板引用 - 父直接访问子
父组件通过 ref 属性直接获取子组件的实例,从而调用其方法或访问其属性。//子组件 (Child.vue):使用 defineExpose 显式暴露需要被父组件访问的属性或方法。
<script setup>
import { ref } from 'vue';
const childState = ref('Child Data');
const childMethod = () => {
console.log('Method called in child!');
};
// 1. 暴露给父组件
defineExpose({
childState,
childMethod
});
</script>//父组件 (Parent.vue):使用 ref 和相同的变量名来获取模板引用。
<script setup>
import { ref, onMounted } from 'vue';
import Child from './Child.vue';
// 2. 创建一个 ref 来持有子组件的引用
const childRef = ref(null);
onMounted(() => {
// 3. 在生命周期后,可以访问子组件暴露出的属性和方法
console.log(childRef.value.childState); // 'Child Data'
childRef.value.childMethod(); // 'Method called in child!'
});
</script>
<template>
<!-- 将 ref 绑定到子组件上 -->
<Child ref="childRef" />
</template>特性:
1.命令式操作:常用于需要直接操控子组件 DOM 元素或调用其方法的场景(如输入框聚焦、触发动画等)。
2.谨慎使用:应优先考虑使用 props 和 events 进行数据流管理,避免过度使用 refs 导致代码结构混乱。

页: [1]
查看完整版本: vue3父子组件通信常用方法