defineExpose 暴露子组件的方法给父组件(不直接调用父组件方法,但可用于间接通信)虽然这不是直接调用父组件方法的方式,但 defineExpose 可以让父组件通过 ref 访问子组件的方法和属性,从而可能实现一些间接的通信逻辑。
这是 Vue 中最推荐的父子组件通信方式。子组件通过 $emit 触发一个自定义事件,父组件监听这个事件并作出响应。
子组件 (Child.vue 或 Child.tsx):
<script setup>
import { defineEmits } from 'vue';
const emit = defineEmits<{
(e: 'callParentMethod', data: any): void;
}>();
function childMethod() {
const someData = { message: "Hello from child" };
emit('callParentMethod', someData);
}
</script>
<template>
<button @click="childMethod">Call Parent Method</button>
</template>
父组件:
<template>
<Child @callParentMethod="parentMethod" />
</template>
<script setup>
import Child from './Child.vue';
interface ChildData {
message: string;
}
function parentMethod(dataFromChild: ChildData) {
console.log(dataFromChild.message);
}
</script>
provide 和 inject(适用于跨多层级组件通信)虽然这不是直接调用父组件方法,但 provide 和 inject 可以在组件树中任意位置进行通信。你可以在父组件中使用 provide 提供一个方法或数据,然后在子组件(或任何子组件的子孙组件)中使用 inject 接收它。
父组件:
<script setup>
import { provide } from 'vue';
// 定义一个带参数的方法
function parentMethod(message) {
console.log('父组件的方法被调用了,参数是:', message);
}
// 提供这个方法
provide('parentMethod', parentMethod);
</script>
<template>
<ChildComponent />
</template>
子组件:
<script setup>
import { inject } from 'vue';
const parentMethod = inject('parentMethod') as (message) => void;
function callParent() {
if (parentMethod) {
parentMethod();
}
}
</script>
<template>
<button @click="callParent">Call Parent Method</button>
</template>
综上所述,虽然 <script setup> 使得直接访问 $parent 或 $emit 变得不那么直接,但 Vue 提供了其他强大的机制来实现父子组件之间的通信。在这些机制中,通过自定义事件进行通信是最直接和推荐的方式。
总结:
