Ссылки на элементы шаблона
Вакансии vuejobs.com
Хотя декларативная модель рендеринга Vue абстрагирует от большинства прямых операций с DOM, все же могут быть случаи, когда нужен прямой доступ к базовым элементам DOM. Для этого можно использовать специальный атрибут ref:
template
<input ref="input">
ref - специальный атрибут, аналогичный атрибуту key, о котором говорилось в главе v-for. Он позволяет получить прямую ссылку на определенный элемент DOM или экземпляр дочернего компонента после его монтирования. Это может быть полезно, когда нужно, например, программно выставить фокус на поле ввода при монтировании компонента или инициализировать стороннюю библиотеку на элементе.
Доступ к ссылкам
Чтобы получить ссылку с помощью Composition API, нужно объявить ref с тем же именем:
vue
<script setup>
import { ref, onMounted } from 'vue'
// объявляем ref-ссылку на элемент
// имя должно совпадать со значением ref в шаблоне
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
Требуется v3.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>
Если дочерний компонент использует Options API или не использует <script setup>,
Исключением здесь является то, что компоненты, использующие <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 } (ссылки автоматически разворачиваются, как и для обычных экземпляров).
См. также: Типизированные ссылки на шаблоны компонентов