Vue中子组件如何等待父组件异步事件调用返回?
Hey there! Let's break down what's going wrong and how to fix it in Vue.
First, the core issue: this.$emit('click') doesn't return the result of the parent's async function. $emit is just a way to trigger an event—it doesn't pass back return values from listener callbacks. That's why your await isn't working as expected.
Here are two solid approaches to make the child component wait for the parent's async action to resolve:
1. Pass the Async Function via Props (Similar to React)
This is the most straightforward approach when you need to get a return value from the parent's action. You can pass the async function directly as a prop, then call it in the child and await its result.
Modified Child Component (MyDialog.vue)
<template> <div class="text-center"> <v-dialog v-model="dialog" width="500" > <template v-slot:activator="{ on, attrs }"> <v-btn color="red lighten-2" dark v-bind="attrs" v-on="on" > Click Me </v-btn> </template> <v-card> <v-card-title class="headline grey lighten-2"> Privacy Policy </v-card-title> <v-card-text> Some text </v-card-text> <v-divider></v-divider> <v-card-actions> <v-spacer></v-spacer> <v-btn color="primary" text @click="handleAsyncAction" > I accept </v-btn> </v-card-actions> </v-card> </v-dialog> </div> </template> <script lang="ts"> import Vue from "vue"; import Component from "vue-class-component"; @Component({ props: { asyncAction: { type: Function, required: true } } }) export class MyDialog extends Vue { dialog: boolean = false; async handleAsyncAction() { try { // Call the parent's async function and wait for its result const value = await this.asyncAction(); if(value === 'x') { this.dialog = false; // Close dialog if result matches expectation } else { alert('error!'); } } catch (err) { // Handle any errors from the parent's async request alert('Request failed!'); } } } </script>
Modified Parent Component
<template> <div> <!-- Pass the async function as a prop instead of using an event listener --> <MyDialog :async-action="makeSomeAjaxRequest" /> </div> </template> <script type="ts"> import Vue from "vue"; import Component from "vue-class-component"; import MyDialog from "./MyDialog" @Component({ components: { MyDialog } }) export default class ParentComponent extends Vue { async makeSomeAjaxRequest() { const response = await fetch('http://example.com'); const data = await response.text(); // Properly parse the fetch response return data; } } </script>
2. Wrap the Event Emit in a Promise (Event-Based Approach)
If you prefer sticking with Vue's event system instead of props, you can wrap the event trigger in a Promise. This works because the parent's callback returns a Promise, which we can capture and await in the child.
Modified Child Component
<template> <!-- Same template as your original code --> </template> <script lang="ts"> import Vue from "vue"; import Component from "vue-class-component"; @Component() export class MyDialog extends Vue { dialog: boolean = false; async handleAsyncAction() { try { // Check if a listener exists for the 'click' event if (this.$listeners.click) { // Call the listener and wait for its Promise to resolve const value = await this.$listeners.click(); if(value === 'x') { this.dialog = false; } else { alert('error!'); } } } catch (err) { alert('Request failed!'); } } } </script>
Parent Component (Minimal Changes)
Just ensure your async function returns a Promise (which it already does, since it's marked async):
<template> <div> <MyDialog @click="makeSomeAjaxRequest" /> </div> </template> <script type="ts"> // Same script as your original, with proper response parsing import Vue from "vue"; import Component from "vue-class-component"; import MyDialog from "./MyDialog" @Component({ components: { MyDialog } }) export default class ParentComponent extends Vue { async makeSomeAjaxRequest() { const response = await fetch('http://example.com'); const data = await response.text(); return data; } } </script>
Quick Notes:
- In your original code,
dialog = falsewas missingthis.—fixed that in all examples. - Always add
try/catchblocks when working with async code to handle unexpected errors gracefully. - The props approach is generally more explicit and easier to maintain for this use case, as it makes the child's dependency on the async function clear.
内容的提问来源于stack exchange,提问作者silicakes

