Skip to content
sumnail

Vue3のTeleportを使用したモーダルの実装

created at : 2024/08/16

Vue3
Teleport
モーダル
VitePress

Teleport を使用してモーダルを実装します。

実装方法

Vue3 の標準コンポーネントの Teleport を使用して、モーダルを実装します。

VitePress では Teleport の向き先は、to="body"のみ対応しており、別要素を指定する場合は<ClientOnly>を使用するか、postRendar hook を使用します。

実装例

ボタンをクリックすると、画面全体を覆うモーダルが表示されます。

モーダル外をクリックしても、モーダルが閉じます。

サンプル

サンプルコード
vue
<template>
  <button class="open-button" @click="show = !show">Open Modal</button>
  <Teleport to="body">
    <div v-show="show" class="modal-mask" @click="show = !show">
      <div
        class="modal-container"
        @click.stop="() => console.log('stop propagation')"
      >
        <h2 class="modal-title">Title</h2>
        <p class="modal-content">Content</p>
        <button class="modal-button" @click="show = false">Close</button>
      </div>
    </div>
  </Teleport>
</template>

<script setup lang="ts">
import { ref } from "vue";

const show = ref(false);
</script>

<style scoped>
.open-button {
  margin: 8px;
  padding: 8px 16px;
  color: var(--text-color);
  background-color: var(--main-color);
  border: 1px solid var(--main-color);
  border-radius: 4px;
}

.modal-container {
  position: relative;
  width: 350px;
  height: 250px;
  padding: 16px;
  background-color: #fff;
  border-radius: 4px;
}

.modal-title {
  margin: 0;
  font-size: 1.5rem;
  font-weight: bold;
}

.modal-content {
  margin: 8px 0;
  font-size: 1rem;
}

.modal-button {
  position: absolute;
  bottom: 8px;
  right: 8px;
  padding: 8px 16px;
  border: 1px solid #ccc;
  border-radius: 4px;
}

.modal-mask {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 9999;
}
</style>