
・Vue.jsのTeleportの使い方は?
こんな疑問にお答えします。
Vue.jsで作業してるとき、特定の要素やコンポーネントのみDOM階層の外側に反映させたいときないでしょうか。
実はそれ「Teleport」というコンポーネントを使えば実装可能です。
今回は自分用のメモとして「Teleport」についてまとめてみました!

参考にどうぞ
ということで、この記事では「Vue.jsのTeleportの使い方」について解説していきます!
・Vue.jsのTeleportの基本的な使い方
・Vue.jsのTeleportの注意点やその他


目次
【解説】Vue.jsのTeleportの基本的な使い方
そんな「Teleport」を使った内容やコードがこちら。
<template>
<Teleport to="body">
<p>ここのコンテンツは外側に反映されています。</p>
</Teleport>
</template>

「Teleport」で囲われたコンテンツが、DOM階層の外側のbodyタグ下の直前に反映されていますよね。
こんな感じで外側にテレポートさせるように移動できるのが「Teleport」の特徴です。
使い方の重要な点がこちら↓
①:「Teleport」タグで囲む
②:「Teleport」タグにto属性をつける
③:「Teleport」タグ内に移動させたいコンテンツを記述
順に解説してきます。
まず「Teleport」タグで囲みましょう。
<template>
<Teleport>
</Teleport>
</template>
そしたら「Teleport」タグにto属性をつけます。
この値に「CSSのセレクタ」や「タグ名」を記述しましょう。
すると指定した部分の一番下に反映されます。
「to=”.text”」
「to=”#news”」
「to=”header”」 みたいな感じですね。
今回は例として「body」と記述しました。
<template>
<Teleport to="body">
</Teleport>
</template>
つまりbodyタグの一番下に挿入されるということです。
あとは移動させたいコンテンツ内容を、「Teleport」タグの中に記述すれば完了です。
<template>
<Teleport to="body">
<p>ここのコンテンツは外側に反映されています。</p>
</Teleport>
</template>
これでDOM階層の外側に反映させることができました
(今回でいうとbodyタグの一番下直前)↓

ちなみに元々コンテンツがあった部分はコメントアウトされます。

基本的な使い方はこんな感じだね
【解説】Vue.jsのTeleportの注意点やその他【条件付きの無効化可能】
「Teleport」タグの基本的な使い方は先述したとおり。
ただ他にも注意点やその他の使い方があります。
・to属性の値の場所
・to属性の値が複数同じ場合
・モーダル実装時に便利
・条件付きで無効化可能
順に見ていきましょう。
to属性の値を指定するときに注意点あります。
それはto属性の値はVue.js全体がマウントされるより外側にいるのが理想的ということ。
つまり下記コードの場合は「#app」より外側の場所に、to属性の値をいれるということです。
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
ちなみに複数の「Teleport」タグを使っていて、同じto属性の値を指定したときは上から順にテレポートされます。
つまり下記コードのように記述すると、、
<template>
<Teleport to="body">
<p>Aのコンテンツです</p>
</Teleport>
<Teleport to="body">
<p>Bのコンテンツです</p>
</Teleport>
</template>
このように「Aのコンテンツです」が上にくるということですね↓

モーダルを実装するときは、フルスクリーンのときが多いですよね。
その場合タグの位置的に、bodyの一番下に挿入したほうが良い構造になります。
「Teleport」タグを使えばbodyタグ一番下に移動できるので、モーダル実装時にかなり便利。
ちなみに「Transitin」と「Teleport」を一緒に使えば、アニメーションがあるモーダルが実装できますよ。

「Teleport」タグは「:disable」を使えば、無効化することが可能です。
つまり下記コードだと無効化され、テレポートされません。
<template>
<Teleport to="body" :disabled="true">
<p>Aのコンテンツです</p>
</Teleport>
</template>
ボタンクリックしたら有効化、無効化されるコードを書いてみました↓
<script setup lang="ts">
import { ref } from 'vue';
const teleportItem = ref(true)
</script>
<template>
<button @click="teleportItem = !teleportItem">有効無効ボタン</button>
<Teleport to="body" :disabled="teleportItem">
<p>Aのコンテンツです</p>
</Teleport>
</template>
こんな感じで条件により「Teleport」タグを無効化にするという使い方も可能ですね。


【解説】Vue.jsのTeleportの使い方【条件付きの無効化可能】:まとめ
- 「Teleport」タグを使えばDOM階層の外側に挿入可能
- 「Teleport」タグのto属性の値の一番下が挿入場所になる
- 「Teleport」タグが複数あり、同じto属性の値の場合は上から順にテレポートされる
- 「Teleport」タグは「:disable」を使えば無効化可能

Vue.jsでTeleportを使う時はためしてみてね!