Refs и прямой доступ к элементам

В SkateJS refs используются для прямого доступа к DOM-элементам внутри компонента. Это особенно важно при работе с интерактивными элементами, сторонними библиотеками или нестандартными манипуляциями с DOM, когда стандартные механизмы реактивного обновления компонентов оказываются недостаточными.

Определение и использование ref

ref создаётся в компоненте через объект refs в классе компонента. Каждому ключу в объекте refs соответствует элемент DOM, к которому требуется прямой доступ. Привязка происходит автоматически через атрибут ref в шаблоне компонента.

import { Component, h, define } from 'skatejs';

class MyComponent extends Component {
  static get is() { return 'my-component'; }

  static get props() {
    return {};
  }

  // Объект refs для хранения ссылок на элементы
  refs = {
    inputField: null,
    submitButton: null
  };

  renderCallback() {
    return (
      <div>
        <input ref="inputField" type="text" />
        <button ref="submitButton">Отправить</button>
      </div>
    );
  }

  focusInput() {
    // Прямой доступ к DOM элементу через refs
    this.refs.inputField.focus();
  }
}

define(MyComponent);

В примере выше ключи inputField и submitButton становятся ссылками на соответствующие элементы DOM после первого рендера.

Автоматическое обновление ссылок

Система refs SkateJS автоматически обновляет ссылки при повторных рендерах. Это означает, что при динамическом изменении содержимого DOM, ссылки в объекте refs всегда остаются актуальными.

renderCallback() {
  const showButton = true;
  return (
    <div>
      <input ref="inputField" />
      {showButton ? <button ref="submitButton">Отправить</button> : null}
    </div>
  );
}

Если showButton станет false, ссылка this.refs.submitButton будет автоматически очищена и установлена в null. Это предотвращает ошибки при обращении к несуществующим элементам.

Работа с ref в методах жизненного цикла

Наиболее надёжное место для работы с refs — методы жизненного цикла компонента:

  • rendered() — вызывается после первого рендера, когда DOM полностью готов.
  • updated(prevProps, prevState) — вызывается после обновления компонента, ссылки на элементы уже актуализированы.
rendered() {
  // Установка фокуса на поле ввода после рендера
  this.refs.inputField.focus();
}

updated() {
  // Можно выполнять любые DOM-операции с актуальными элементами
  console.log('Кнопка:', this.refs.submitButton);
}

Динамическая генерация refs

SkateJS позволяет использовать ref внутри циклов или динамически создаваемых элементов, но ключи должны быть уникальными. В таких случаях можно генерировать имена программно:

renderCallback() {
  const items = ['Пункт 1', 'Пункт 2', 'Пункт 3'];
  return (
    <ul>
      {items.map((item, index) => (
        <li ref={`item${index}`} key={index}>{item}</li>
      ))}
    </ul>
  );
}

logRefs() {
  console.log(this.refs.item0); // доступ к первому элементу списка
}

Важно помнить, что динамические refs создаются только после рендера, поэтому обращаться к ним раньше не имеет смысла.

Использование ref с кастомными элементами

Ссылки на кастомные компоненты позволяют вызывать их публичные методы напрямую:

<custom-input ref="customInput" />

this.refs.customInput.clear();

При этом необходимо, чтобы компонент custom-input предоставлял соответствующий метод clear. SkateJS обеспечивает, что ссылка указывает на сам экземпляр компонента, а не на его внутренний DOM.

Советы по эффективной работе с refs

  1. Использовать refs только для элементов, с которыми требуется прямое взаимодействие, например, управление фокусом, интеграция с внешними библиотеками или манипуляции с canvas.
  2. Не использовать refs как замену реактивного обновления состояния компонента. SkateJS эффективно обновляет DOM через свойства и состояние, и чрезмерное использование refs может привести к конфликтам.
  3. При динамическом рендере проверять наличие ссылки перед обращением, чтобы избежать ошибок при условных элементах.
  4. Для удобства и читаемости кода группировать refs в объект, а не хранить отдельные свойства для каждого элемента.

Заключение по концепции

Refs в SkateJS предоставляют безопасный и удобный механизм прямого доступа к DOM-элементам и экземплярам компонентов, сохраняя их актуальными при изменении структуры компонента. Понимание жизненного цикла компонентов и правильное использование refs позволяет создавать сложные интерактивные элементы с минимальными усилиями и высокой надёжностью.