通过另一个对话框(模态)打开 Healdess UI 对话框(模态)会自动关闭前一个对话框(模态)吗? (添加了CodeSandBox复制链接)

问题描述 投票:0回答:1

我正在我的

HeadlessUI/Vue
应用程序中使用
Nuxt 3
组件来构建对话框/模态框。我正在使用最新版本
"@headlessui/vue": "^1.7.22"
并在Chrome最新浏览器中进行开发。

我正在使用

DialogPanel1.vue
创建一个
headlessui/vue
。我在
DialogPanel1.vue
中有一个按钮,单击它我将打开
DialogPanel2.vue
,但在
DialogPanel2.vue
内,当我单击任意位置时,它会自动关闭位于
DialogPanel1.vue
后面的
DialogPanel2.vue

CodeSandBox 中的最小复制存储库

为什么会自动关闭

DialogPanel1
?我想确保仅当我单击
DialogPanel1
中的关闭按钮而不是单击
DialogPanel1.vue
时才关闭
DialogPanel2
。我尝试添加
@click.stop
@mousedown.stop
来防止事件传播,但它仍然不起作用。有谁可以告诉我这个问题吗?

以下是我的完整代码

/pages/index.vue
:

<template>
  <DialogPanel1 />
</template>
  
<script setup>
</script>

以下是我的组件

/component/DialogPanel1.vue
:

<template>
  <div class="mb-2">
    <button
      type="button"
      @click="openModal1"
      class="flex secondary-button text-secondary dark:bg-transparent dark:hover:text-secondary dark:hover:bg-slate-700 mx-auto justify-center items-center rounded border focus:ring-0 focus:outline-none font-medium px-5 py-2.5 text-center min-w-[8rem] sm:min-w-[10rem] lg:min-w-[12rem]"
    >
      <span class="pr-1"> Open Modal-1 </span>
    </button>
  </div>

  <TransitionRoot appear :show="modal1" as="template">
    <Dialog as="div" @close="closeModal" class="relative z-30">
      <div class="fixed inset-0 overflow-y-auto">
        <div
          class="flex min-h-full items-center justify-center p-4 text-center"
        >
          <DialogPanel
            class="dark:bg-slate-800 w-full transform overflow-auto rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all z-20"
          >
            THIS IS MODAL-1
            <button
              class="flex secondary-button text-secondary dark:bg-transparent dark:hover:text-secondary dark:hover:bg-slate-700 mx-auto justify-center items-center rounded border focus:ring-0 focus:outline-none font-medium px-5 py-2.5 text-center min-w-[8rem] sm:min-w-[10rem] lg:min-w-[12rem]"
              @click="openModal2"
            >
              MODAL-2
            </button>
          </DialogPanel>
        </div>
      </div>
    </Dialog>
  </TransitionRoot>

  <DialogPanel2 :modal2="modal2" @closeModal="hideModal2" />
</template>
    
<script setup>
import { TransitionRoot, Dialog, DialogPanel } from "@headlessui/vue";

const modal1 = ref(false);
const modal2 = ref(false);

//Function to open Modal-1
const openModal1 = () => {
  console.log("Opening Modal-1");
  modal1.value = true;
};

//Close the modal on click of the button
const closeModal = () => {
  console.log("CLOSE MODAL-1");
  modal1.value = false;
};

//Function to open Modal-2
const openModal2 = () => {
  console.log("Open MODAL-2");
  modal2.value = true;
};

const hideModal2 = () => {
  console.log("Closing MODAL-2");
  modal2.value = false;
};
</script>

以下是我的

/components/DialogPanel2.vue

<template>
  <TransitionRoot
    appear
    :show="modal2"
    as="template"
    @close="closeModal"
    @click.native.stop.prevent
  >
    <Dialog
      :initialFocus="focusRef"
      as="div"
      @click.native.stop.prevent
      class="relative z-50"
    >
      <div class="fixed inset-0 overflow-y-auto">
        <div
          class="flex min-h-full items-center justify-center p-4 text-center"
        >
          <DialogPanel
            @click.native.stop.prevent
            class="pt-5 w-full max-w-xl overflow-y-auto transform overflow-visible rounded-2xl bg-white dark:bg-slate-800 p-6 align-middle shadow-xl transition-all"
          >
            THIS IS MODAL-2

            <span class="text-black dark:text-white">Field-1</span>
            <input
              ref="focusRef"
              v-model="test.one"
              type="text"
              class="relative w-full h-full bg-gray-50 dark:text-black dark:bg-gray-700 dark:border-gray-600 border-gray-300 border rounded text-center block overflow-hidden"
            />

            <span class="text-black dark:text-white">Field-2</span>
            <input
              v-model="test.two"
              type="text"
              class="relative w-full h-full bg-gray-50 dark:text-white dark:bg-gray-700 dark:border-gray-600 border-gray-300 border rounded text-center block overflow-hidden"
            />

            <button class="mt-4" @click="closeModal">Close</button>
          </DialogPanel>
        </div>
      </div>
    </Dialog>
  </TransitionRoot>
</template>
  
  <script setup>
import { TransitionRoot, Dialog, DialogPanel } from "@headlessui/vue";

const props = defineProps({
  modal2: {
    type: Boolean, //Show/hide the modal based on the flag
    required: false,
  },
});

const emits = defineEmits(["closeModal"]);
const focusRef = ref(null);

//Reference variables
const modal2 = ref(props.modal2);
const test = ref({});

watch(
  () => props.modal2,
  async (newValue) => {
    modal2.value = newValue;
  }
);

const closeModal = () => {
  console.log("CLOSE MODAL-2");
  modal2.value = false;
  emits("closeModal");
};
</script>

为什么点击

DialogPanel2.vue
上的任意位置会自动关闭之前的对话框
DialogPanel1.vue
?我尝试从
@close="closeModal"
中删除
DialogPanel1.vue
,这会阻止
DialogPanel1.vue
的关闭,但这也使得我无法编辑
DialogPanel2.vue
中的任何字段,这意味着焦点仍然保留在
DialogPanel1.vue
因此我无法访问或聚焦于
DialogPanel2.vue
。对
DialogPanel1.vue
进行以下更改:
<TransitionRoot appear :show="modal1" as="template">
但此后当我无法访问
DialogPanel2.vue
中的输入字段时。

我仍然无法确定根本原因并解决它,任何建议都会非常有帮助。

问题:Codesandbox

以下是我的问题 GIF: ModalCosure

vue.js vuejs3 nuxt.js headless-ui
1个回答
0
投票

我无法阅读完整的代码,但似乎对话框使用了“外部点击”之类的东西,它会将任何不在元素或其子元素内部的点击视为“外部点击”,并将触发关闭功能。在您的情况下,您的

<DialogPanel2>
放置在
<DialogPanel1>
之外,因此当
<DialogPanel1>
打开且
<DialogPanel2>
也打开时,任何不是
<DialogPanel1>
子级的内容都将被视为在其外部(在这种情况下,
<DialogPanel2>
被视为在
<DialogPanel1>
之外),因此点击将触发
<DialogPanel1>
的关闭。

最简单的修复(取决于您的用例)是将

<DialogPanel2>
移动到
<DialogPanel1>
的内部,这样它就不会被视为外部点击,如下所示:

  <TransitionRoot appear :show="modal1" as="template" @close="closeModal">
    <Dialog as="div" class="relative z-30">
      <div class="fixed inset-0 overflow-y-auto">
        <div
          class="flex min-h-full items-center justify-center p-4 text-center"
        >
          <DialogPanel
            class="dark:bg-slate-800 w-full transform overflow-auto rounded-2xl bg-gray-200 p-6 text-left align-middle shadow-xl transition-all z-20"
          >
            THIS IS MODAL-1
            <button
              class="flex secondary-button text-secondary dark:bg-transparent dark:hover:text-secondary dark:hover:bg-slate-700 mx-auto justify-center items-center rounded border focus:ring-0 focus:outline-none font-medium px-5 py-2.5 text-center min-w-[8rem] sm:min-w-[10rem] lg:min-w-[12rem]"
              @click="openModal2"
            >
              MODAL-2
            </button>
            <DialogPanel2 :modal2="modal2" @closeModal="hideModal2" /><!-- move it here-->
          </DialogPanel>
        </div>
      </div>
    </Dialog>
  </TransitionRoot>
© www.soinside.com 2019 - 2024. All rights reserved.