Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

x-ref и $refs

Обычно Alpine меняет страницу сам, по данным. Но иногда нужен сам элемент: поставить курсор в поле, прокрутить список, измерить размер. Директива x-ref даёт элементу имя, а объект $refs возвращает элемент по этому имени — без querySelector.

Имя и обращение

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<div x-data>
  <input x-ref="title" placeholder="Новая задача">
  <button @click="$refs.title.focus()">Перейти к полю</button>
</div>

Клик по кнопке ставит курсор в поле ввода. $refs.title — обычный DOM-элемент, у него есть все методы из уроков о работе со страницей.

Фокус после добавления

В списке дел удобно возвращать курсор в поле после добавления задачи, чтобы сразу вводить следующую:

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<div x-data="{
  title: '',
  tasks: [],
  add() {
    if (this.title === '') return;
    this.tasks.push(this.title);
    this.title = '';
    this.$refs.title.focus();
  }
}">
  <input x-ref="title" x-model="title" @keydown.enter="add()" placeholder="Новая задача">
  <button @click="add()">Добавить</button>
  <p x-text="tasks.join(', ')"></p>
</div>

Нажмите кнопку мышью — задача добавится, а курсор вернётся в поле. Внутри методов $refs доступен через this, как и данные.

Прокрутка списка

Ещё один частый случай — прокрутить контейнер к последнему элементу:

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<div x-data="{ tasks: ['Задача 1', 'Задача 2', 'Задача 3'] }">
  <ul x-ref="list" style="height: 80px; overflow: auto; border: 1px solid #ccc">
    <template x-for="task in tasks">
      <li x-text="task"></li>
    </template>
  </ul>
  <button @click="tasks.push('Задача ' + (tasks.length + 1)); $nextTick(() => $refs.list.scrollTop = $refs.list.scrollHeight)">
    Добавить
  </button>
</div>

Каждая новая задача добавляется внизу, и список прокручивается к ней. $nextTick ждёт, пока Alpine добавит пункт на страницу, — подробнее о нём в уроке о магических свойствах.

Когда $refs не нужен

Если задачу можно решить данными, решайте данными. Прочитать текст поля — это x-model, а не $refs.title.value. Спрятать элемент — x-show, а не $refs.box.style.display. $refs оставляют для действий, которых нет в данных: фокус, прокрутка, размеры, вызов методов сторонних библиотек.

Частая ошибка

Обращаться к x-ref из соседнего компонента. $refs видит элементы своего компонента и тех, внутри которых он лежит, но не компонентов рядом. Если кнопка и поле стоят в двух соседних элементах с x-data, $refs.title будет undefined и вызов focus() закончится ошибкой. Объедините их в один компонент или передайте сигнал событием через $dispatch.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.