1

我想在 vue3 中使用无头 ui 模态,但问题是如果模态是一个组件,我不明白如何从父级(App.vue)切换模态。

我试图在 Modal.vue 中传递一个道具,但它不起作用,我的策略是使用 modalActive 道具并观察它并调用适当的函数来切换模式,但它根本不起作用。

无头 UI 中的示例使用了一个按钮,但它位于它自身的组件内部,因此显然它可以毫无问题地访问该组件的功能。

我的代码:

应用程序.vue

<template>
  <Modal>
    <template v-slot:default>
      <LoginForm />
    </template>
  </Modal>
</template>


<script setup lang="ts">

import Modal from './components/Modal.vue';
import LoginForm from './components/LoginForm.vue';
import { ref } from 'vue';

</script>

模态的.vue

<template>
    <TransitionRoot appear :show="isOpen" as="template">
        <Dialog as="div" @close="closeModal">
            <div class="fixed inset-0 z-10 overflow-y-auto">
                <div class="min-h-screen px-4 text-center">
                    <TransitionChild
                        as="template"
                        enter="duration-300 ease-out"
                        enter-from="opacity-0"
                        enter-to="opacity-100"
                        leave="duration-200 ease-in"
                        leave-from="opacity-100"
                        leave-to="opacity-0"
                    >
                        <DialogOverlay class="fixed inset-0" />
                    </TransitionChild>
                    <span class="inline-block h-screen align-middle" aria-hidden="true">&#8203;</span>
                    <TransitionChild
                        as="template"
                        enter="duration-300 ease-out"
                        enter-from="opacity-0 scale-95"
                        enter-to="opacity-100 scale-100"
                        leave="duration-200 ease-in"
                        leave-from="opacity-100 scale-100"
                        leave-to="opacity-0 scale-95"
                    >
                        <div
                            class="inline-block w-full max-w-md p-6 my-8 overflow-hidden text-left align-middle transition-all transform bg-white shadow-xl rounded-2xl"
                        >
                            <slot></slot> <!-- slot for forms -->
                        </div>
                    </TransitionChild>
                </div>
            </div>
        </Dialog>
    </TransitionRoot>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue'
import {
    TransitionRoot,
    TransitionChild,
    Dialog,
    DialogOverlay,
    DialogTitle,
} from '@headlessui/vue'

const isOpen = ref(true)


function closeModal() {
    isOpen.value = false

}
function openModal() {
    isOpen.value = true
}

</script>

4

1 回答 1

1

您应该defineExpose与 一起使用$refs

<script setup>
import { ref, watch, defineExpose } from 'vue'

...      

const closeModal =  function() {
    isOpen.value = false
}
const openModal = function() {
    isOpen.value = true
}
  
defineExpose({
  openModal,
  closeModal
})
  
</script>

对您的组件的模板引用:

  <Modal ref="modal">

openModal以及Vue App 中的方法:

components: {
      Modal
    },
    methods: {
      openModal() {
        this.$refs.modal.openModal();
      }
    }

这是一个工作版本:Vue SFC Playground

以下是 Vue 3 文档中了解解决方案的重要部分:

于 2021-11-10T20:11:50.317 回答