cxhl818 2025-10-13 10:28 采纳率: 40%
浏览 22
已结题

vben admin中嵌套modal关闭问题

使用vben admin,在制作消息通知模块时,遇到以下问题:

img

这是第一层弹窗

img

这是第二层弹窗
两层弹窗使用的都是vben modal,大体代码如下:

<script setup lang="ts">
import { useVbenModal } from '@vben/common-ui';

import { $t } from '#/locales';

const [Modal, modalApi] = useVbenModal({
  draggable: true,
  fullscreenButton: false,
  class: 'w-[1000px]',
  onCancel() {
    modalApi.close();
  },
  onConfirm: async () => {},
  async onOpenChange(isOpen: boolean) {
    if (isOpen) {
      await initData();
    }
  },
  title: $t('ui.widgets.setting'),
});
/**
 * 初始化数据
 */
async function initData() {}
</script>
<template>
  <Modal>1</Modal>
</template>


现在的问题是,当我打开两层弹窗时,点击第二层弹窗以外,第一层弹窗以内的区域时,两个弹窗会同时关闭,这个效果显然是不合理的。
想知道怎么样才能点击第二层弹窗以外,第一层弹窗以内的区域时,只关闭第二层弹窗

  • 写回答

5条回答 默认 最新

  • 檀越@新空间 2025-10-13 10:29
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    在使用 Vben AdminuseVbenModal 时,如果你遇到了嵌套 Modal 弹窗关闭行为异常的问题,即:点击第二层弹窗以外、第一层弹窗以内的区域时,两个弹窗同时关闭,这是由于默认的 Modal 配置中未正确区分“模态层级”所导致的。


    ✅ 问题原因分析

    你目前使用的 useVbenModal 创建的是一个独立的 Modal 实例,但当你在第一层 Modal 内部再次调用 useVbenModal 创建第二层 Modal 时,第二个 Modal 并没有被正确地设置为第一个 Modal 的子级,因此它会默认具有“全局”层级,从而导致点击外部区域时触发了所有 Modal 的关闭。


    ✅ 解决方案(重点)

    为了实现“只关闭当前弹窗,不影响其他弹窗”,你需要确保:

    1. 第二层 Modal 被设置为第一层 Modal 的子级
    2. 禁止第二层 Modal 的外层点击关闭行为

    以下是详细的解决步骤和代码示例:


    1. 修改第一层 Modal 的配置

    确保第一层 Modal 允许内部嵌套 Modal,并且不阻止事件冒泡。

    const [Modal, modalApi] = useVbenModal({
      draggable: true,
      fullscreenButton: false,
      class: 'w-[1000px]',
      onCancel() {
        modalApi.close();
      },
      onConfirm: async () => {},
      async onOpenChange(isOpen: boolean) {
        if (isOpen) {
          await initData();
        }
      },
      title: $t('ui.widgets.setting'),
      // 设置 modal 的 z-index 层级,防止被遮挡
      zIndex: 1000,
    });
    

    2. 创建第二层 Modal 时,将其作为第一层 Modal 的子级

    在第一层 Modal 内部,使用 modalApi 来打开第二层 Modal,并设置其为“子 Modal”。

    // 在第一层 Modal 内部的方法中打开第二层 Modal
    async function openSecondModal() {
      const [SecondModal, secondModalApi] = useVbenModal({
        title: '这是第二层弹窗',
        content: '这是第二层弹窗内容',
        width: 500,
        // 禁止点击外部关闭
        closeOnClickMask: false,
        // 设置为第一层 Modal 的子级
        parent: modalApi,
        onOk: async () => {
          secondModalApi.close();
        },
        onCancel: async () => {
          secondModalApi.close();
        },
      });
    
      SecondModal();
    }
    

    3. 在模板中添加按钮触发第二层 Modal

    <template>
      <Modal>
        <div>这是第一层弹窗</div>
        <button @click="openSecondModal">打开第二层弹窗</button>
      </Modal>
    </template>
    

    ✅ 总结

    | 步骤 | 操作 | |------|------| | 1 | 使用 useVbenModal 创建第一层 Modal,设置合适的 zIndex。 | | 2 | 在第一层 Modal 内部调用 useVbenModal 创建第二层 Modal,并通过 parent: modalApi 设置为子 Modal。 | | 3 | 设置 closeOnClickMask: false,防止点击外部区域关闭第二层 Modal。 | | 4 | 保证 onOkonCancel 仅关闭当前 Modal。 |


    ✅ 修改后的完整代码示例

    <script setup lang="ts">
    import { useVbenModal } from '@vben/common-ui';
    import { $t } from '#/locales';
    
    const [Modal, modalApi] = useVbenModal({
      draggable: true,
      fullscreenButton: false,
      class: 'w-[1000px]',
      onCancel() {
        modalApi.close();
      },
      onConfirm: async () => {},
      async onOpenChange(isOpen: boolean) {
        if (isOpen) {
          await initData();
        }
      },
      title: $t('ui.widgets.setting'),
      zIndex: 1000,
    });
    
    async function initData() {}
    
    async function openSecondModal() {
      const [SecondModal, secondModalApi] = useVbenModal({
        title: '这是第二层弹窗',
        content: '这是第二层弹窗内容',
        width: 500,
        closeOnClickMask: false,
        parent: modalApi,
        onOk: async () => {
          secondModalApi.close();
        },
        onCancel: async () => {
          secondModalApi.close();
        },
      });
    
      SecondModal();
    }
    </script>
    
    <template>
      <Modal>
        <div>这是第一层弹窗</div>
        <button @click="openSecondModal">打开第二层弹窗</button>
      </Modal>
    </template>
    

    ✅ 注意事项

    • 如果你使用的是 Vue 3 + Composition API,请确保你使用的是最新的 @vben/common-ui 版本。
    • 如果你仍然遇到层级问题,可以尝试手动设置 zIndex 或使用 CSS 控制 Modal 层级。

    如需进一步优化 Modal 嵌套体验,也可以考虑使用 ModalStack自定义 Modal 管理器 来管理多层 Modal 的显示与关闭逻辑。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 10月17日
  • 创建了问题 10月13日