如何在 Nuxt 3/vue 3 中从标题组件调用并显示模态组件?

huangapple go评论60阅读模式
英文:

Nuxt3/vue3 how to show modal component that is called from header component?

问题

以下是你要翻译的内容:

Header.vue

<template>
    <header class="header sticky-top">
        <nav class="container-fluid navbar-light bg-light">
            <div class="row justify-content-start">
                <div class="col text-end p-3">
                    <button @click="showModal = true" type="button" class="btn">Register</button>
                </div>
            </div>
            <Modal v-show="showModal"/>
        </nav>
    </header>
</template>

<script lang="ts">
import Modal from '~~/components/Modal.vue';

export default {
    components:{
        Modal
    },
    data(){
        return{
            showModal: false
        }
    },
}
</script>

DefaultLayout.vue

<template>
    <Header />
    <main class="p-4 ">
        <div class="container-fluid ">
            <slot />
        </div>
    </main>
    <Footer />
</template>

<script lang="ts">
import Header from '~~/components/Header.vue';
import Footer from '~~/components/Footer.vue';
export default {
    components: {
        Footer,
        Header
    },
}
</script>

index.vue(这是我的主页)

<template>
    <default-layout>
        <Listings/>
    </default-layout>
</template>

<script lang="ts">
import DefaultLayout from '~~/layouts/DefaultLayout.vue';
import Listings from '~~/components/Listings.vue';
export default {
    setup() {

    },
    components: {
        DefaultLayout,
        Listings
    }
}
</script>

Modal.vue

<template>
    <Teleport to="body">
        <div class="modal show" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        ...
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                        <button type="button" class="btn btn-primary">Save changes</button>
                    </div>
                </div>
            </div>
        </div>
    </Teleport>
</template>

<script lang="ts">
export default{
    props:{
        showModal: Boolean
    }
}
</script>
英文:

I am using nuxt3/vue3. I am having a difficult time to call the modal based on my header component. I just put the modal inside the header component and use Teleport function to teleport the modal in the body based on the showModal value but it doesnt work. Here is what I tried

Header.vue

&lt;template&gt;
    &lt;header class=&quot;header sticky-top&quot;&gt;
        &lt;nav class=&quot;container-fluid navbar-light bg-light&quot;&gt;
                &lt;div class=&quot;row justify-content-start&quot;&gt;
                    &lt;div class=&quot;col text-end p-3&quot;&gt;
                        &lt;button @click=&quot;showModal = true&quot; type=&quot;button&quot; class=&quot;btn&quot;&gt;Register&lt;/button&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
                &lt;Modal v-show=&quot;showModal&quot;/&gt;
        &lt;/nav&gt;
    &lt;/header&gt;
&lt;/template&gt;

&lt;script lang=&quot;ts&quot;&gt;
import Modal from &#39;~~/components/Modal.vue&#39;;

export default {
    components:{
        Modal
    },
    data(){
        return{
            showModal: false
        }
    },
}
&lt;/script&gt;

DefaultLayout.vue

&lt;template&gt;
        &lt;Header /&gt;
            &lt;main class=&quot;p-4 &quot;&gt;
                &lt;div class=&quot;container-fluid &quot;&gt;
                    &lt;slot /&gt;
                &lt;/div&gt;
            &lt;/main&gt;
        &lt;Footer /&gt;
&lt;/template&gt;

&lt;script lang=&quot;ts&quot;&gt;
import Header from &#39;~~/components/Header.vue&#39;;
import Footer from &#39;~~/components/Footer.vue&#39;;
export default {
    components: {
        Footer,
        Header
    },
}
&lt;/script&gt;

index.vue (which is my homepage)

&lt;template&gt;
    &lt;default-layout&gt;
        &lt;Listings/&gt;
    &lt;/default-layout&gt;
&lt;/template&gt;

&lt;script lang=&quot;ts&quot;&gt;
import DefaultLayout from &#39;~~/layouts/DefaultLayout.vue&#39;;
import Listings from &#39;~~/components/Listings.vue&#39;;
export default {
    setup() {

    },
    components: {
        DefaultLayout,
        Listings
    }
}
&lt;/script&gt;

Modal.vue

&lt;template&gt;
    &lt;Teleport to=&quot;body&quot;&gt;
        &lt;div class=&quot;modal show&quot; id=&quot;exampleModal&quot; tabindex=&quot;-1&quot; aria-labelledby=&quot;exampleModalLabel&quot;&gt;
            &lt;div class=&quot;modal-dialog&quot;&gt;
                &lt;div class=&quot;modal-content&quot;&gt;
                    &lt;div class=&quot;modal-header&quot;&gt;
                        &lt;h1 class=&quot;modal-title fs-5&quot; id=&quot;exampleModalLabel&quot;&gt;Modal title&lt;/h1&gt;
                        &lt;button type=&quot;button&quot; class=&quot;btn-close&quot; data-bs-dismiss=&quot;modal&quot; aria-label=&quot;Close&quot;&gt;&lt;/button&gt;
                    &lt;/div&gt;
                    &lt;div class=&quot;modal-body&quot;&gt;
                        ...
                    &lt;/div&gt;
                    &lt;div class=&quot;modal-footer&quot;&gt;
                        &lt;button type=&quot;button&quot; class=&quot;btn btn-secondary&quot; data-bs-dismiss=&quot;modal&quot;&gt;Close&lt;/button&gt;
                        &lt;button type=&quot;button&quot; class=&quot;btn btn-primary&quot;&gt;Save changes&lt;/button&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/Teleport&gt;
&lt;/template&gt;

&lt;script lang=&quot;ts&quot;&gt;
export default{
    props:{
        showModal: Boolean
    }
}
&lt;/script&gt;

答案1

得分: 2

我的当前处理模态的方法是将模态组件挂载到全局应用程序模板中,并通过Pinia存储变量来控制其可见性:

我使用Composition API,但希望你能明白我的意思。

英文:

My current approach to modals is to mount the modal component into global app template and controll its visibility by a Pinia store variable:

I use Composition API, but hopefully you'll get the idea.

答案2

得分: 0

根据@ellrohir的回应,我已经为Nuxt 3与Pinia和Primevue开发了一个简单的方法。

我的存储文件modalStore.ts:

export const useModalStore = defineStore({
    id: 'modal-store',
    state: () => {
        return {
            displayModal: false,
            modalTitle: '',
            modalText: '',
        };
    },
    actions: {
        showModal(title: string, text: string): void {
            this.modalTitle = title;
            this.modalText = text;
            this.displayModal = true;
        },
        closeModal(): void {
            this.displayModal = false;
        },
    },
});

我的app.vue:

<script setup>
    const modalStore = useModalStore();
</script>
<template>
    <DialogLogin />
</template>

我的modal DialogLogin:

<script setup>
    const modalStore = useModalStore();
</script>

<template>
    <Dialog
        :header="$t('login')"
        v-model:visible="modalStore.displayModal"
        :breakpoints="{ '960px': '75vw', '640px': '90vw' }"
        :style="{ width: '50vw' }"
        :position="position"
        :modal="true"
    >
        <!-- login component form -->
        <FormLogin />

        <!-- footer template -->
        <template #footer>
            <Button
                :label="$t('cancel')"
                icon="pi pi-times"
                @click="modalStore.closeModal()"
                class="p-button-text"
            />
        </template>
    </Dialog>
</template>

然后,我使用按钮来激活它:

<Button
    label="Login"
    icon="pi pi-sign-in"
    @click="modalStore.showModal()"
></Button>
英文:

based on the response of @ellrohir, I have developed a simple method for Nuxt 3 with Pinia and Primevue

my store file modalStore.ts

export const useModalStore = defineStore({
	id: &#39;modal-store&#39;,
	state: () =&gt; {
		return {
			displayModal: false,
			modalTitle: &#39;&#39;,
			modalText: &#39;&#39;,
		};
	},
	actions: {
		showModal(title: string, text: string): void {
			this.modalTitle = title;
			this.modalText = text;
			this.displayModal = true;
		},
		closeModal(): void {
			this.displayModal = false;
		},
	},
});

my app.vue

&lt;script setup&gt;
	const modalStore = useModalStore();
&lt;/script&gt;
&lt;template&gt;
	&lt;DialogLogin /&gt;
&lt;/template&gt;

my modal DialogLogin

&lt;script setup&gt;
	const modalStore = useModalStore();
&lt;/script&gt;

&lt;template&gt;
	&lt;Dialog
		:header=&quot;$t(&#39;login&#39;)&quot;
		v-model:visible=&quot;modalStore.displayModal&quot;
		:breakpoints=&quot;{ &#39;960px&#39;: &#39;75vw&#39;, &#39;640px&#39;: &#39;90vw&#39; }&quot;
		:style=&quot;{ width: &#39;50vw&#39; }&quot;
		:position=&quot;position&quot;
		:modal=&quot;true&quot;
	&gt;
		&lt;!-- login component form --&gt;
		&lt;FormLogin /&gt;

		&lt;!-- footer template --&gt;
		&lt;template #footer&gt;
			&lt;Button
				:label=&quot;$t(&#39;cancel&#39;)&quot;
				icon=&quot;pi pi-times&quot;
				@click=&quot;modalStore.closeModal()&quot;
				class=&quot;p-button-text&quot;
			/&gt;
		&lt;/template&gt;
	&lt;/Dialog&gt;
&lt;/template&gt;

then I activate it with a button

		&lt;Button
			label=&quot;Login&quot;
			icon=&quot;pi pi-sign-in&quot;
			@click=&quot;modalStore.showModal()&quot;
		&gt;&lt;/Button&gt;

huangapple
  • 本文由 发表于 2023年2月14日 03:34:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75440449.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定