一、父组件触发子组件方法
- 使用 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>
- 使用自定义事件
适用场景 :需要传递参数给子组件方法
<!-- 父组件 -->
<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>
二、子组件触发父组件方法
- 使用自定义事件(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>
- 使用回调函数(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>
三、父组件给子组件传数据
- 使用 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>
- 使用 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>
四、子组件给父组件传数据
- 使用自定义事件(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>
- 使用 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>