Teleport для портирования контента

Teleport в Vue.js — это механизм, позволяющий перемещать часть DOM-контента в другое место документа вне текущей иерархии компонентов. Он особенно полезен для работы с модальными окнами, всплывающими подсказками, диалогами и другими элементами интерфейса, которые должны визуально находиться вне основного потока приложения.


Основы использования Teleport

Базовый синтаксис Teleport:

<template>
  <teleport to="body">
    <div class="modal">
      Контент модального окна
    </div>
  </teleport>
</template>
  • Атрибут to указывает CSS-селектор элемента, в который будет перемещён контент.
  • Всё, что находится внутри <teleport>, визуально отрисуется в указанном контейнере, но логически останется частью компонента, сохраняя реактивность и события.

Ключевые особенности

  1. Сохранение реактивности Перемещённый контент полностью сохраняет доступ к данным компонента, в котором он объявлен.
<template>
  <teleport to="#popup-root">
    <div>{{ message }}</div>
  </teleport>
</template>

<script>
export default {
  data() {
    return {
      message: 'Привет из компонента!'
    }
  }
}
</script>
  1. События остаются локальными События, привязанные к элементам внутри Teleport, продолжают работать так, как если бы элементы находились в исходной иерархии.
<teleport to="body">
  <button @click="handleClick">Нажми меня</button>
</teleport>

<script>
export default {
  methods: {
    handleClick() {
      console.log('Кнопка нажата');
    }
  }
}
</script>
  1. Динамическое управление Teleport можно включать и отключать условно с помощью 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, но управление вложенными порталами требует внимательного контроля за условными рендерингами и целевыми селекторами.


Практические сценарии использования

  1. Модальные окна

Teleport позволяет модальному окну находиться в корне документа, что исключает проблемы с overflow или z-index внутри вложенных контейнеров.

<teleport to="body" v-if="showModal">
  <div class="modal">
    <h2>Заголовок модалки</h2>
    <p>Контент модального окна</p>
    <button @click="showModal = false">Закрыть</button>
  </div>
</teleport>
  1. Всплывающие подсказки и тултипы

Использование Teleport позволяет выводить подсказки поверх других элементов, без изменения структуры DOM родительского компонента.

<teleport to="body" v-if="hovered">
  <div class="tooltip" :style="{ top: y + 'px', left: x + 'px' }">
    {{ tooltipText }}
  </div>
</teleport>
  1. Контекстные меню

Контекстное меню, которое должно открываться поверх всего интерфейса, удобно реализовать через 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>

Взаимодействие с переходами (Transitions)

Teleport полностью совместим с компонентами <transition> и <transition-group>. Для анимации появления или исчезновения контента модальных окон достаточно обернуть Teleport в <transition>:

<transition name="fade">
  <teleport to="body" v-if="showModal">
    <div class="modal">Контент с анимацией</div>
  </teleport>
</transition>

Итоговые ключевые моменты

  • Teleport перемещает DOM-контент, сохраняя реактивность и события.
  • Используется для модальных окон, подсказок, контекстных меню и других элементов, требующих вывода вне родительского потока.
  • Поддерживает динамическое управление через v-if и динамические селекторы.
  • Полностью совместим с Vue Transition для анимаций.
  • При работе со scoped-стилями необходимо учитывать, что перемещённый контент наследует только глобальные или контейнерные стили.