Vue3父子组件通信方法总结

一、父组件触发子组件方法

  1. 使用 ref 引用

适用场景 :父组件需要直接调用子组件的方法

复制代码
<!-- 父组件 -->
<template>
  <Child ref="childRef" />
  <button @click="callChildMethod">调用子组件方法</button>
</template>

<script setup>
import { ref } from 'vue';
import Child from './Child.vue';

const childRef = ref(null);

const callChildMethod = () => {
  childRef.value.childMethod();
};
</script>

<!-- 子组件 (Child.vue) -->
<template>
  <div>子组件</div>
</template>

<script setup>
import { defineExpose } from 'vue';

const childMethod = () => {
  console.log('子组件方法被调用');
};

// 暴露方法给父组件
defineExpose({
  childMethod
});
</script>
  1. 使用自定义事件

适用场景 :需要传递参数给子组件方法

复制代码
<!-- 父组件 -->
<template>
  <Child ref="childRef" />
  <button @click="triggerChildEvent">触发子组件事件</button>
</template>

<script setup>
import { ref } from 'vue';
import Child from './Child.vue';

const childRef = ref(null);

const triggerChildEvent = () => {
  childRef.value.$emit('custom-event', { message: 'Hello' });
};
</script>

<!-- 子组件 (Child.vue) -->
<template>
  <div>子组件</div>
</template>

<script setup>
import { onMounted } from 'vue';

const emit = defineEmits(['custom-event']);

onMounted(() => {
  // 监听自定义事件
  emit('custom-event', { message: 'Initial' });
});

// 也可以在子组件内部监听事件
// 注意:Vue 3 中组件实例的 $on 已移除,推荐使用 props 或 provide/inject
</script>

二、子组件触发父组件方法

  1. 使用自定义事件(defineEmits)

适用场景 :子组件向父组件传递事件

复制代码
<!-- 子组件 -->
<template>
  <button @click="triggerParentMethod">触发父组件方法</button>
</template>

<script setup>
const emit = defineEmits(['parent-event']);

const triggerParentMethod = () => {
  emit('parent-event', { data: '子组件数据' });
};
</script>

<!-- 父组件 -->
<template>
  <Child @parent-event="handleParentEvent" />
</template>

<script setup>
import Child from './Child.vue';

const handleParentEvent = (data) => {
  console.log('父组件方法被调用,数据:', data);
};
</script>
  1. 使用回调函数(props)

适用场景 :父组件传递函数给子组件,子组件调用

复制代码
<!-- 父组件 -->
<template>
  <Child :callback="parentMethod" />
</template>

<script setup>
import Child from './Child.vue';

const parentMethod = (data) => {
  console.log('父组件方法被调用,数据:', data);
};
</script>

<!-- 子组件 -->
<template>
  <button @click="callParentMethod">调用父组件回调</button>
</template>

<script setup>
const props = defineProps({
  callback: {
    type: Function,
    default: () => {}
  }
});

const callParentMethod = () => {
  props.callback({ message: '子组件调用' });
};
</script>

三、父组件给子组件传数据

  1. 使用 defineProps

适用场景 :父组件向子组件传递静态或动态数据

复制代码
<!-- 父组件 -->
<template>
  <Child :message="parentMessage" :count="parentCount" />
</template>

<script setup>
import { ref } from 'vue';
import Child from './Child.vue';

const parentMessage = ref('Hello Vue 3');
const parentCount = ref(10);
</script>

<!-- 子组件 -->
<template>
  <div>{{ message }}</div>
  <div>{{ count }}</div>
</template>

<script setup>
import { watch } from 'vue';

const props = defineProps({
  message: {
    type: String,
    default: ''
  },
  count: {
    type: Number,
    default: 0
  }
});

watch(() => props.message, (newVal) => {
  console.log('收到新的消息:', newVal);
});
</script>
  1. 使用 provide/inject

适用场景 :深层组件嵌套时的跨层级数据传递

复制代码
<!-- 父组件 -->
<script setup>
import { ref, provide } from 'vue';
import Child from './Child.vue';

const sharedData = ref('共享数据');

// 提供数据
provide('sharedData', sharedData);
</script>

<!-- 子组件(或深层子组件) -->
<script setup>
import { inject } from 'vue';

// 注入数据
const sharedData = inject('sharedData');

console.log('注入的数据:', sharedData.value);
</script>

四、子组件给父组件传数据

  1. 使用自定义事件(defineEmits)

适用场景 :子组件向父组件传递数据

复制代码
<!-- 子组件 -->
<template>
  <button @click="sendDataToParent">传递数据给父组件</button>
</template>

<script setup>
const emit = defineEmits(['update-data']);

const sendDataToParent = () => {
  emit('update-data', {
    value: '子组件值',
    message: '子组件数据'
  });
};
</script>

<!-- 父组件 -->
<template>
  <Child @update-data="handleUpdate" />
</template>

<script setup>
import { ref } from 'vue';
import Child from './Child.vue';

const parentData = ref(null);

const handleUpdate = (data) => {
  console.log('收到子组件数据:', data);
  parentData.value = data;
};
</script>
  1. 使用 v-model 双向绑定

适用场景 :需要实现父子组件数据双向绑定

复制代码
<!-- 父组件 -->
<template>
  <Child v-model="parentValue" />
  <p>父组件值:{{ parentValue }}</p>
</template>

<script setup>
import { ref } from 'vue';
import Child from './Child.vue';

const parentValue = ref('初始值');
</script>

<!-- 子组件 -->
<template>
  <input v-model="localValue" @input="updateValue" />
</template>

<script setup>
import { ref, watch } from 'vue';

const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  }
});

const emit = defineEmits(['update:modelValue']);

const localValue = ref(props.modelValue);

watch(() => props.modelValue, (newVal) => {
  localValue.value = newVal;
});

const updateValue = () => {
  emit('update:modelValue', localValue.value);
};
</script>
相关推荐
SameX3 分钟前
ArkTS 做 5 态数据流 —— 咖啡电量的代谢状态机怎么驱动 UI
前端
Dovis(誓平步青云)4 分钟前
启元 T1 Pro 人机相声搭档:语音-触摸双通道的启元机器人节奏引擎设计
开发语言·前端·javascript·microsoft·交互
ruanno_top5 分钟前
能点,但 Tab 不到:两个组件把「可操作」做了一半
vue.js
爱吃烧烤的技术渣6 分钟前
别再手写 CRUD 了:我把 Element Plus 的工作量压缩成一份列 schema
前端·vue.js
MetWeave9 分钟前
风的三十年:一个机场的风在变小吗:10,958 天的账(《风不是一个数》系列第 6 篇)
前端·数据可视化
青烟小生12 分钟前
前端实时协同编辑与 CRDT 冲突解决实战:从 OT 到 Yjs 底层原理(完整版)
前端
陈随易15 分钟前
神级 Skill,让 AI 用 HTML 代替 Markdown 回复
前端·后端·程序员
eidnxndrdkdns23 分钟前
PE 自校验的三个坑:恒失败、基址变化、以及被漏在外面的检测器
前端
90后的晨仔27 分钟前
解决 Android 构建报错:Unable to delete file .../file-map.txt
android·前端
Yuhano32 分钟前
W4. RAG 让 Agent 拥有"外部记忆"
前端·aigc