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>Пов'язані
