当前位置: 首页 > news >正文

前端Vue中,如何实现父组件打开子组件窗口等待子组件窗口关闭后继续执行父组件逻辑

1.需求:

  1. 当执行 this.isOpenArchives = true 打开子组件弹窗时,等待子组件关闭并回传数据后,才继续往下执行后续逻辑(即实现“同步等待”效果)。
  2. 子组件关闭时能回传数据给父组件。

2.流程详细概要:

2.1.父组件中打开子组件窗口

async uf_add_brda(as_klx, as_kh, as_sfzh){ 

        //  打开子组件窗口

        this.isOpenArchives = true;

        //  data 就是子组件回传的数据

        const { confirmed, data } = await this.showArchivesDialog();

        // confirmed 为true是sucess调用,反之为close调用
if (!confirmed) return;

        // 取出data中封装的数据
        lstr_out = data.lstr_mess

        //  这里写后续逻辑

        //      .

        //      .

        //      .

}

const { confirmed, data } = await this.showArchivesDialog();

if (confirmed) {

  // data 就是子组件回传的数据

  // 这里写后续逻辑

}

这样,只有等子组件关闭并回传数据后,后续代码才会继续执行,完全等价于 PB 的同步弹窗+数据回传。 

2.1.1在组件中引入子组件 

//     省略

//        .

//        .

//        .

<m-dialog :title="dialogTitle"  v-model.sync="isOpenArchives" top="10vh" show-footer :closeOnModal="false"

      :destroyOnClose="false">

      <Archives v-if="isOpenArchives"  :inTheDialog="true" :pget="pget" ref="archives" @close="isOpenArchives = false" @success="isOpenArchives = false">

      </Archives>

    </m-dialog>

//     省略

//        .

//        .

//        .

import MDialog from "../../../components/MForm/MDialog.vue";

import Archives from "../archives/index.vue";

//     省略

//        .

//        .

//        .

export default {

  components: {

    DynamicQuery,

    OutpatientReturnReg,

    Archives,

    FpSet,

    MDialog,

    Charge,

  },

//     省略

//        .

//        .

//        .

}

2.1.2封装弹窗显示方法

// 封装弹窗显示方法(返回Promise)

    async  showArchivesDialog() {

       // 打开子组件弹窗

      this.isOpenArchives = true;

      await this.$nextTick(); // 关键!

      if (!this.$refs.archives) {

        return { confirmed: false };

      }

      return new Promise((resolve) => {

        this.$refs.archives.$once('success', (data) => {

          this.isOpenArchives = false;

          resolve({ confirmed: true, data });

        });

        this.$refs.archives.$once('close', () => {

          this.isOpenArchives = false;

          resolve({ confirmed: false });

        });

      });

    },

1. 不要直接用 this.isOpenArchives = true,而是用 await this.showArchivesDialog()。

 2. 子组件(Archives)里,关闭弹窗时用 $emit('success', data) 或 $emit('close'),父组件就能收到。

2.1.3子组件代码

<template>
<Container leftWidth="100%" :topVisibel="!inTheDialog">
<template #top>
<div>
<m-button name="save" :disabled="saveDisabled" :loading="saveLoading" :debounceTime="1000" :isDebounce="true" @click="save"
>保存</m-button
>
<m-button
name="save"
:disabled="saveDisabled"
:loading="saveLoading"
:isDebounce="true"
:debounceTime="1000" 
@click="save(1)"
v-if="currentId === ''"
>保存并关闭</m-button
>
<m-button name="close" @click="$tab.closePage()">关闭</m-button>
</div>
</template>
<template #left>
<div class="left-layout" v-loading="formLoading">
<div class="footer" v-if="inTheDialog">
<div>
<m-button name="" v-if="currentId === ''" @click="clearForm"
>清空</m-button
>
<el-checkbox
v-model="isShowJhInfo"
style="margin-left: 20px"
class="btn-ml"
>监护人信息</el-checkbox
>
</div>
<div>

        // 下面的save和close方法处理完成后会关闭窗口,将数据返回给父窗口
<m-button name="save" :isDebounce="true" :debounceTime="1000"  @click="save" :loading="saveLoading">保存</m-button>
<m-button name="close" @click="close">关闭</m-button>
</div>
</div>
</div>
</template>
<m-dialog
:title="dialogTitle"
v-model.sync="showDAXZ"
top="10vh"
show-footer
appendToBody
:closeOnModal="false"
:destroyOnClose="false"
>
<archivesDAXZ
v-if="showDAXZ"
:pget="daxzPget"
:inTheDialog="true"
ref="daxzRef"
@copySuccess="copySuccess"
@close="showDAXZ=false">
</archivesDAXZ>
</m-dialog>

  </Container>
</template>

save方法 

async save(isSave) {try{await jdbq_jd(modifyParams).then((res) => {this.saveLoading = false;this.$message.success("保存成功");// 调用父组件中的success方法并返回数据this.$emit("success", res.data);if (isSave === 1) {this.$tab.closePage();}if (!this.inTheDialog) {this.clearForm();}});}finally{this.saveLoading = false;}// 关闭页面this.$emit("close");},

close方法

close() {
// 调用父组件中的close方法this.$emit("close");
},

3.子组件如何回传数据? 

在 Archives 组件里,关闭弹窗时这样写:

// 成功时
this.$emit('success', data);
// 取消时
this.$emit('close');

4.补充解释this.$refs.archives.$once

这段代码 this.$refs.archives.$once是 ​​Vue.js​​ 中的语法,其含义如下:


4.1 ​​解释this.$refs.archives
  • this​:指向当前 Vue 组件实例。

  • $refs​:Vue 的特殊属性,用于访问模板中通过 ref注册的 DOM 元素或子组件。

  • archives​:模板中定义的 ref名称,例如:

<child-component ref="archives" />
<!-- 或 -->
<div ref="archives"></div>

  • ​结果​​:this.$refs.archives获取名为 archives的子组件实例或 DOM 元素(通常用于访问子组件)。


4.2 解释​$once
  • $once​ 是 Vue 实例的方法,用于​​监听一个自定义事件,但仅触发一次​​。触发后监听器会自动移除。

  • 语法:vm.$once(eventName, callback)

    • eventName:要监听的事件名称(字符串)。

    • callback:事件触发时执行的回调函数。

4.3完整含义

this.$refs.archives.$once表示:

​在子组件 archives上注册一个一次性事件监听器​​。当 archives子组件内部触发指定事件时,父组件的回调函数会执行一次,随后自动解除监听。

4.4典型使用场景

 // 父组件中
this.$refs.archives.$once('some-event', (payload) => {
console.log('事件仅触发一次!', payload);
});

子组件如何触发?

在子组件(archives)内部,通过 $emit触发事件:

this.$emit('some-event', { data: '传递的数据' });

 

4.5⚠️ 注意事项
  1. ​Vue 3 的变化​​在 Vue 3 中,$on$once和 $off已被移除(RFC)。替代方案:

    ​​ 使用 v-on:event.once​ 在模板中:

<child-component @some-event.once="handleEvent" />

​手动实现一次性监听​​(在 setup 或方法中): 

import { onMounted } from 'vue';

setup() {
const handleEventOnce = (payload) => {
console.log(payload);
// 移除监听逻辑...
};
// 在适当位置手动调用 $on 并移除(需自己实现)

    2. ​​确保 $refs可用​$refs在组件渲染完成后才填充,避免在 created生命周期中使用(建议在 mounted或事件回调中使用)。

4.6总结
  • this.$refs.archives.$once​:在子组件 archives上绑定一个​​一次性事件监听器​​。

  • ​用途​​:适用于只需响应一次的事件(如弹窗关闭、初始化完成通知等)。

  • ​Vue 3 用户​​:改用模板的 .once修饰符或手动事件管理。


5.总结

  • 用 await this.showArchivesDialog() 实现“同步等待弹窗关闭并回传数据”。
  • 子组件用 $emit('success', data) 或 $emit('close') 回传数据/关闭信号。

 

http://www.dtcms.com/a/282546.html

相关文章:

  • DeepSeek(18):SpringAI+DeepSeek大模型应用开发之会话日志
  • 单片机(STM32-中断)
  • JS逆向 - YandexSmartCaptcha (worker线程)
  • 基于WebRTC构建应用的可复用模块
  • 下载webrtc M114版本源码只能使用外网googlesource源-命令版
  • i.mx8 RTC问题
  • TEngine学习
  • 【Noah-MP模型】陆面生态水文模拟与多源遥感数据同化的实践技术应用
  • JavaScript进阶篇——第六章 内置构造函数与内置方法
  • alpineLinux修改包管理为国内源
  • 越野小车结构设计\越野小车设计cad【6张】三维图+设计说明书
  • 【Java】【力扣】101.对称二叉树
  • 数据结构与算法——Leetcode215. 数组中的第K个最大元素
  • 中国1km分辨率逐月平均气温数据集 - matlab按shp批量裁剪
  • Git远程仓库与协作技巧详解
  • 【add vs commit】Git 中的 add 和 commit 之间的区别
  • 秘塔AI搜索的深度研究推出:它的“免费午餐”还能走多远?
  • NULL值处理:索引优化与业务设计实践指南
  • GIT版本回退
  • 堆排序算法详解:原理、实现与C语言代码
  • ubuntu--自启动程序
  • Docker Compose 清理指南:`down` 与 `down -v` 的核心区别与使用场景
  • Jenkins credentials 增加了github credential 但是在Git SCM 凭证中不显示
  • 基于SpringBoot+Uniapp球场预约小程序(腾讯地图API、Echarts图形化分析、二维码识别)
  • 如何用 Charles 中文版抓包工具高效调试 API 并优化网络性能
  • 自适应哈希索引 和 日志缓冲区
  • 结构体(二)
  • XXE漏洞1-XXE 漏洞简介-XML 语法-DTD 讲解-外部实体讲解
  • 【React Native】安装配置 Expo Router
  • HTML基础P1 | HTML基本元素