在 Vue 中,我们常通过 emit 自定义事件实现父子组件通信(子组件触发事件、父组件监听),也可借助 eventBus 事件总线完成任意组件间的通信。
实际开发中,有时需要获取自定义事件的执行结果,以推进后续逻辑处理。但 emit 本身无返回值,且事件监听函数可能包含异步逻辑,该如何将执行结果回传给触发事件的组件呢?
下文将说明 emit 自定义事件在同步、异步逻辑下的返回值获取方式,eventBus 事件总线的处理方式可参考此逻辑。
一、同步逻辑
子组件触发事件,父组件以同步逻辑处理。
结论:通过回调函数获取到执行结果。
父组件:
js
<template>
<ChildComponent @childEvent="handleChildEvent" />
</template>
<script setup>
import ChildComponent from "./ChildComponent.vue";
function handleChildEvent(callback) {
const result = "Data from Parent";
callback(result);
}
</script>
子组件:
js
<template>
<el-button type="primary" @click="triggerEvent"
>Trigger Child Event</el-button
>
</template>
<script setup>
const emit = defineEmits(["childEvent"]);
function triggerEvent() {
emit("childEvent", (result) => {
console.log("parent result: ", result);
// 继续子组件中的逻辑
// ......
});
}
</script>
一、异步逻辑
子组件触发事件,父组件以异步逻辑处理。
结论:通过Promise对象拿到执行结果。
父组件:
js
<template>
<ChildComponent @childEvent="handleChildEvent" />
</template>
<script setup>
import ChildComponent from "./ChildComponent.vue";
function otherLogic() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("Data from Parent");
}, 2000);
});
}
async function handleChildEvent({ resolve, reject }) {
const result = await otherLogic();
resolve(result);
}
</script>
子组件:
js
<template>
<el-button type="primary" @click="triggerEvent"
>Trigger Child Event</el-button
>
</template>
<script setup>
const emit = defineEmits(["childEvent"]);
async function triggerEvent() {
try {
const result = await new Promise((resolve, reject) => {
emit("childEvent", { resolve, reject });
});
console.log("parent result: ", result);
} catch (e) {
console.log(e);
}
}
</script>
总结
无论是同步还是异步逻辑,本质都是通过回调函数的方式,将父组件(或其他组件)的执行结果回传,而 resolve 本质也是一种回调函数。