Для чего используется teleport во Vue 3
Что проверяют
Понимаете ли вы, какую проблему вёрстки решает Teleport и что при переносе в DOM остаётся на месте. Следом часто спрашивают, работают ли provide/inject и события в телепортированном контенте и что будет при SSR.
Как отвечать
<Teleport> это встроенный компонент Vue 3, который рендерит содержимое в другой узел DOM, например <Teleport to="body">. Логически контент остаётся дочерним для компонента, где объявлен: пропсы, emit, provide/inject, реактивность и Vue Devtools работают как обычно. Меняется только физическое место узлов в документе.
Зачем это нужно:
- модалки: у предка с
overflow: hiddenокно обрежется, а у предка сtransformилиfilterэлемент сposition: fixedпозиционируется относительно этого предка, а не окна; z-index: предок со своим контекстом наложения не даёт вложенному элементу подняться выше соседей, как ни увеличивай число;- всплывающие элементы: тосты, тултипы, меню, которые лежат поверх всего интерфейса.
Детали API:
to: CSS-селектор или сам DOM-элемент, цель должна существовать к моменту монтирования;disabled: рендерит контент на месте, удобно, когда на мобильном меню встроено в страницу, а на десктопе всплывает;defer: появился в Vue 3.5, откладывает поиск цели до конца текущего цикла рендера, и цель может отрисовать то же приложение;- общая цель: несколько
Teleportв один контейнер добавляют контент по порядку.
При SSR контент телепорта рендерится отдельно и вставляется в страницу вручную, иначе будет рассинхрон гидратации. В Nuxt для этого есть контейнер #teleports.
Где спотыкаются
Телепортируют в элемент, которого ещё нет в DOM, и получают предупреждение о ненайденной цели. Контейнер нужно отрендерить раньше или добавить defer.
Ждут, что нативное событие всплывёт к DOM-родителю компонента. Всплытие идёт по реальному положению узлов, то есть к body, а не к обёртке, где объявлен Teleport.
Считают модалку готовой после переноса в body. Удержание фокуса, aria-modal, закрытие по Escape и блокировка прокрутки остаются на вас.