Teleport в Vue.js — это механизм, позволяющий перемещать часть DOM-контента в другое место документа вне текущей иерархии компонентов. Он особенно полезен для работы с модальными окнами, всплывающими подсказками, диалогами и другими элементами интерфейса, которые должны визуально находиться вне основного потока приложения.
Базовый синтаксис Teleport:
<template>
<teleport to="body">
<div class="modal">
Контент модального окна
</div>
</teleport>
</template>
to указывает CSS-селектор элемента, в который
будет перемещён контент.<teleport>, визуально
отрисуется в указанном контейнере, но логически останется частью
компонента, сохраняя реактивность и события.<template>
<teleport to="#popup-root">
<div>{{ message }}</div>
</teleport>
</template>
<script>
export default {
data() {
return {
message: 'Привет из компонента!'
}
}
}
</script>
<teleport to="body">
<button @click="handleClick">Нажми меня</button>
</teleport>
<script>
export default {
methods: {
handleClick() {
console.log('Кнопка нажата');
}
}
}
</script>
v-if:<teleport to="body" v-if="isOpen">
<div class="tooltip">Подсказка</div>
</teleport>
<script>
export default {
data() {
return {
isOpen: false
}
}
}
</script>
Порядок рендеринга Контент Teleport перемещается в момент монтирования, но остаётся частью виртуального DOM исходного компонента. Это важно учитывать при работе с анимациями и вычисляемыми свойствами.
CSS-стили Перемещённый контент наследует стили только от глобальных или родительских селекторов в целевом контейнере. Локальные scoped-стили компонента не применяются, если CSS не глобальный.
Nested Teleports Teleport может содержать другие Teleport, но управление вложенными порталами требует внимательного контроля за условными рендерингами и целевыми селекторами.
Teleport позволяет модальному окну находиться в корне документа, что исключает проблемы с overflow или z-index внутри вложенных контейнеров.
<teleport to="body" v-if="showModal">
<div class="modal">
<h2>Заголовок модалки</h2>
<p>Контент модального окна</p>
<button @click="showModal = false">Закрыть</button>
</div>
</teleport>
Использование Teleport позволяет выводить подсказки поверх других элементов, без изменения структуры DOM родительского компонента.
<teleport to="body" v-if="hovered">
<div class="tooltip" :style="{ top: y + 'px', left: x + 'px' }">
{{ tooltipText }}
</div>
</teleport>
Контекстное меню, которое должно открываться поверх всего интерфейса, удобно реализовать через Teleport. Оно сохраняет реактивность, обработчики кликов и управление состоянием.
<teleport to="body" v-if="menuOpen">
<ul class="context-menu" :style="{ top: posY + 'px', left: posX + 'px' }">
<li @click="action1">Действие 1</li>
<li @click="action2">Действие 2</li>
</ul>
</teleport>
Атрибут to может быть динамическим, что позволяет
переносить контент в разные контейнеры в зависимости от состояния
приложения:
<teleport :to="targetSelector">
<div>Динамический портал</div>
</teleport>
<script>
export default {
data() {
return {
targetSelector: '#dynamic-root'
}
}
}
</script>
Teleport полностью совместим с компонентами
<transition> и <transition-group>.
Для анимации появления или исчезновения контента модальных окон
достаточно обернуть Teleport в <transition>:
<transition name="fade">
<teleport to="body" v-if="showModal">
<div class="modal">Контент с анимацией</div>
</teleport>
</transition>
v-if и
динамические селекторы.