Vue 3のテレポートでUIコンポーネントを別DOMにマウント

Vue 3のテレポートでUIコンポーネントを別DOMにマウント

Vue 3の「Teleport(テレポート)」機能を使用すると、コンポーネントの一部を別のDOM要素にマウントできます。これにより、モーダルやダイアログのようなUI要素をルート要素の外に配置し、スタイルやDOMの構造を整理することが可能になります。本記事ではテレポートの基本から応用例まで詳しく解説します。

テレポートとは

TeleportはVue 3で導入された機能で、コンポーネントの一部を特定のDOM要素に直接レンダリングできます。

<teleport to="body">
  <div>この要素はbodyタグにレンダリングされます。</div>
</teleport>

テレポートの基本構文

テレポートを使用するには`to`属性でターゲットのCSSセレクタを指定します。

<template>
  <teleport to="#modal-root">
    <div class="modal">モーダルコンテンツ</div>
  </teleport>
</template>

テレポートのユースケース

モーダルウィンドウ、ツールチップ、ドロップダウンメニューなど、DOM階層の外で管理したいUI要素に適しています。

モーダルをテレポートで実装

モーダルウィンドウをテレポートで実装します。

// App.vue
<template>
  <button @click="showModal = true">モーダルを開く</button>
  <teleport to="body">
    <div v-if="showModal" class="modal">
      <p>モーダルの内容</p>
      <button @click="showModal = false">閉じる</button>
    </div>
  </teleport>
</template>

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

ターゲット要素の準備

Teleportで指定するターゲット要素が存在しない場合、エラーが発生することがあります。

// index.html
<body>
  <div id="app"></div>
  <div id="modal-root"></div>
</body>

テレポートとスタイルの管理

テレポート要素はルートDOMに移動するため、CSSの適用範囲に注意が必要です。

<style>
.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: white;
  padding: 1rem;
  box-shadow: 0 0 10px rgba(0,0,0,0.2);
}
</style>

動的なテレポートターゲット

`to`属性は動的に変更することも可能です。

<template>
  <teleport :to="dynamicTarget">
    <div>動的ターゲットにテレポート</div>
  </teleport>
  <button @click="changeTarget">ターゲットを変更</button>
</template>

<script>
export default {
  data() {
    return {
      dynamicTarget: '#modal-root',
    };
  },
  methods: {
    changeTarget() {
      this.dynamicTarget = '#another-root';
    },
  },
};
</script>

テレポートのライフサイクルフック

テレポート内のコンポーネントも通常のライフサイクルフックが適用されます。

<teleport to="body">
  <div @mounted="onMounted">マウント時に実行</div>
</teleport>

テレポートとコンポジションAPI

コンポジションAPIを使ってテレポートの状態を管理できます。

<script setup>
import { ref } from 'vue';

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

<template>
  <button @click="showModal = true">モーダルを開く</button>
  <teleport to="body">
    <div v-if="showModal" class="modal">
      <p>モーダルの内容</p>
      <button @click="showModal = false">閉じる</button>
    </div>
  </teleport>
</template>

複数のテレポート要素

複数のテレポートを使用して異なるターゲットに要素をマウントできます。

<teleport to="#header">
  <div>ヘッダー部分</div>
</teleport>
<teleport to="#footer">
  <div>フッター部分</div>
</teleport>

テレポートのパフォーマンス

頻繁に表示・非表示を切り替える要素では、レンダリングコストを考慮する必要があります。

アクセシビリティの考慮

テレポートで要素を移動させると、フォーカス管理が乱れる可能性があります。`aria-*`属性や`focus-trap`ライブラリの使用を検討してください。

まとめ

Vue 3のTeleport機能を使用すると、UIコンポーネントをDOM構造に縛られず、柔軟に配置できます。特にモーダルやツールチップなどの要素でその効果が発揮されます。適切に使用することで、コードの可読性と保守性が向上します。