Референції в шаблонах
Хоча декларативна модель візуалізації Vue абстрагує більшість прямих операцій DOM для вас, можуть бути випадки, коли нам потрібен прямий доступ до базових елементів DOM. Для цього ми можемо використовувати спеціальний атрибут ref
:
template
<input ref="input">
ref
— спеціальний атрибут, подібний до атрибута key
, розглянутого в розділі v-for
. Це дозволяє нам отримати пряме посилання на певний елемент DOM або екземпляр дочірнього компонента після його монтування. Це може бути корисно, коли ви хочете, наприклад, програмно сфокусуватись у полі вводу після монтування компонента або ініціалізувати сторонню бібліотеку для елемента.
Доступ до референцій
Щоб отримати посилання за допомогою композиційного API, нам потрібно оголосити референцію з такою ж назвою:
vue
<script setup>
import { ref, onMounted } from 'vue'
// оголосити референцію для зберігання посилання на елемент
// ім'я має відповідати значенню референції шаблону
const input = ref(null)
onMounted(() => {
input.value.focus()
})
</script>
<template>
<input ref="input" />
</template>
Якщо не використовується <script setup>
, переконайтесь також, що посилання повертається з setup()
:
js
export default {
setup() {
const input = ref(null)
// ...
return {
input
}
}
}
Зауважте, що ви можете отримати доступ до посилання після того, як компонент змонтовано. Якщо ви спробуєте отримати доступ до input
у виразі шаблону буде null
на першому рендері. Це тому, що елемент існує лише після першого відтворення!
Якщо ви намагаєтеся спостерігати за змінами посилання шаблону, обов'язково врахуйте випадок, коли посилання має значення null
:
js
watchEffect(() => {
if (input.value) {
input.value.focus()
} else {
// ще не змонтовано, або елемент було відмонтовано (наприклад, за допомогою v-if)
}
})
Дивіться також: Типізація референцій в шаблонах
Референції всередині v-for
Потрібна версія 3.2.25 або вище
Якщо ref
використовується всередині v-for
, відповідна референція має містити значення масиву, яке буде заповнено елементами після монтування:
vue
<script setup>
import { ref, onMounted } from 'vue'
const list = ref([
/* ... */
])
const itemRefs = ref([])
onMounted(() => console.log(itemRefs.value))
</script>
<template>
<ul>
<li v-for="item in list" ref="itemRefs">
{{ item }}
</li>
</ul>
</template>
Слід зазначити, що масив референцій не гарантує того ж порядку, що й вихідний масив.
Референції в функціях
Замість рядкового ключа атрибут ref
також можна прив'язати до функції, яка буде викликатися під час кожного оновлення компонента, що дає вам повну гнучкість щодо того, де зберігати посилання на елемент. Функція отримує посилання на елемент як перший аргумент:
template
<input :ref="(el) => { /* присвоїти el властивості або референції */ }">
Зауважте, що ми використовуємо динамічне прив'язування :ref
, тому ми можемо передати йому функцію замість рядка-імені референції. Коли елемент демонтовано, аргумент матиме значення null
. Ви, звичайно, можете використовувати метод замість вбудованої функції.
Референція компонента
Цей розділ передбачає знання компонентів. Ви можете пропустити його та повернутися пізніше.
ref
також можна використовувати для дочірнього компонента. У цьому випадку посилання буде вказувати на екземпляр компонента:
vue
<script setup>
import { ref, onMounted } from 'vue'
import Child from './Child.vue'
const child = ref(null)
onMounted(() => {
// child.value буде містити екземпляр <Child >
})
</script>
<template>
<Child ref="child" />
</template>
Якщо дочірній компонент використовує опційний API або не використовує <script setup>
, посилання на екземпляр буде ідентичним this
дочірнього компонента, це означає, що батьківський компонент матиме повний доступ до кожної властивості та методу дочірнього компонента. Це полегшує створення тісно пов'язаних деталей реалізації між батьківським і дочірнім елементом, тому посилання на компоненти слід використовувати лише тоді, коли це абсолютно необхідно - у більшості випадків ви спочатку повинні спробувати реалізувати взаємодію батьківського дочірнього елемента за допомогою стандартних реквізитів і випромінювати інтерфейси.
Винятком є те, що компоненти, які використовують <script setup>
, є приватними за промовчанням: батьківський компонент, який посилається на дочірній компонент за допомогою <script setup>
, не зможе отримати доступ до будь-чого, якщо дочірній компонент не вирішить відкрити публічний інтерфейс за допомогою макросу defineExpose
:
vue
<script setup>
import { ref } from 'vue'
const a = 1
const b = ref(2)
// Макроси компілятора, такі як defineExpose, не потрібно імпортувати
defineExpose({
a,
b
})
</script>
Коли батьківський елемент отримує екземпляр цього компонента через референцію в шаблоні, отриманий екземпляр матиме форму { a: number, b: number }
(референції автоматично розгортаються так само як у звичайних екземплярах).
Дивіться також: типізація референцій в шаблонах для компонент