Teleport
<Teleport>
— це вбудований компонент, який дозволяє нам "телепортувати" частину шаблону компонента у вузол DOM, який існує поза ієрархією DOM цього компонента.
Основне використання
Іноді ми можемо зіткнутися з таким сценарієм: частина шаблону компонента логічно належить до нього, але з візуальної точки зору вона повинна відображатися в іншому місці DOM, поза програмою Vue.
Найпоширенішим прикладом цього є створення повноекранного режиму. В ідеалі ми хочемо, щоб кнопка модального вікна та саме вікно жили в одному компоненті, оскільки вони обидва пов’язані зі станом відкриття/закриття модального вікна. Але це означає, що модальне вікно відображатиметься поруч із кнопкою, глибоко вкладеною в ієрархію DOM програми. Це може створити деякі складнощі під час позиціонування вікна через CSS.
Розглянемо наступну HTML-структуру.
template
<div class="outer">
<h3>Приклад телепортації</h3>
<div>
<MyModal />
</div>
</div>
А ось реалізація <MyModal>
:
vue
<script setup>
import { ref } from 'vue'
const open = ref(false)
</script>
<template>
<button @click="open = true">Відкрити модальне вікно</button>
<div v-if="open" class="modal">
<p>Привіт з модального вікна!</p>
<button @click="open = false">Закрити</button>
</div>
</template>
<style scoped>
.modal {
position: fixed;
z-index: 999;
top: 20%;
left: 50%;
width: 300px;
margin-left: -150px;
}
</style>
Компонент містить <button>
для ініціювання відкриття модального вікна та <div>
з класом .modal
, який має зміст та кнопку для самозакриття.
Під час використання цього компонента в початковій HTML-структурі існує низка потенційних проблем:
position: fixed
лише розміщує елемент відносно вікна перегляду, якщо жоден елемент-предок не має властивостейtransform
,perspective
абоfilter
. Якщо, наприклад, ми маємо намір анімувати предка<div class="outer">
за допомогою перетворення CSS, це порушить макет!z-індекс
модального вікна обмежений елементами, що містяться в ньому. Якщо є інший елемент, який збігається з<div class="outer">
і має вищийz-індекс
, він покриватиме наше вікно.
<Teleport>
забезпечує простий спосіб обійти це, дозволяючи нам вийти за межі вкладеної структури DOM. Змінимо <MyModal>
на використання <Teleport>
:
template
<button @click="open = true">Відкрити модальне вікно</button>
<Teleport to="body">
<div v-if="open" class="modal">
<p>Привіт з модального вікна!</p>
<button @click="open = false">Закрити</button>
</div>
</Teleport>
Ціль to
для <Teleport>
очікує рядок CSS селектору або фактичний вузол DOM. Тут ми, по суті, кажемо Vue «телепортувати цей фрагмент шаблону до тегу body
».
Ви можете натиснути кнопку нижче та перевірити тег <body>
за допомогою інструментів розробника вашого браузера:
Ви можете поєднати <Teleport>
з <Transition>
, щоб створити анімовані модальні вікна - див. Приклад тут.
TIP
Ціль телепорту to
має бути вже в DOM, коли монтується компонент <Teleport>
. В ідеалі це має бути елемент за межами всієї програми Vue. Якщо націлено на інший елемент, відтворений Vue, вам потрібно переконатися, що цей елемент змонтовано перед <Teleport>
.
Використання з компонентами
<Teleport>
змінює лише відтворену структуру DOM, але не впливає на логічну ієрархію компонентів. Тобто, якщо <Teleport>
містить компонент, цей компонент залишатиметься логічним дочірнім компонентом батьківського компонента, що містить <Teleport>
. Передача реквізитів і випромінювання подій працюватимуть так само.
Це також означає, що ін’єкції від батьківського компонента працюють належним чином і що дочірній компонент буде вкладено під батьківським компонентом у Vue Devtools, а не розміщуватиметься там, куди переміщено фактичний вміст.
Вимкнення телепорту
У деяких випадках ми можемо забажати вимкнути <Teleport>
. Наприклад, ми можемо захотіти відобразити компонент як накладення на великих екранах, але вбудовано на мобільному пристрої. <Teleport>
підтримує реквізит disabled
, яку можна динамічно перемикати:
template
<Teleport :disabled="isMobile">
...
</Teleport>
Де стан isMobile
можна динамічно оновлювати, виявляючи зміни медіа-запиту.
Кілька телепортів для однієї цілі
Загальним випадком використання буде повторно використовуваний компонент <Modal>
з можливістю одночасної активності кількох екземплярів. Для такого сценарію кілька компонентів <Teleport>
можуть монтувати свій вміст до одного цільового елемента. Порядок буде простим додаванням - пізніші кріплення будуть розташовані після попередніх у цільовому елементі.
Приклад використання:
template
<Teleport to="#modals">
<div>А</div>
</Teleport>
<Teleport to="#modals">
<div>Б</div>
</Teleport>
Отриманий результат буде таким:
html
<div id="modals">
<div>А</div>
<div>Б</div>
</div>
Пов'язані