Управление фокусом и доступностью

В Riot.js управление фокусом осуществляется через стандартные DOM-методы и события, интегрированные в компоненты. Каждый компонент может содержать элементы с атрибутом ref, который позволяет напрямую ссылаться на них из скриптов компонента. Это обеспечивает гибкое управление фокусом, включая установку, проверку и перемещение между элементами.

Пример использования ref для установки фокуса:

<text-input>
  <input ref="inputField" type="text">
  <script>
    this.on('mount', () => {
      this.refs.inputField.focus()
    })
  </script>
</text-input>

Метод focus() работает синхронно после монтирования компонента. При динамическом создании элементов важно использовать событие mount или updated для корректного применения фокуса.


Работа с управляемыми и неуправляемыми элементами

Riot.js поддерживает оба подхода:

  • Управляемые элементы — состояние элементов хранится в компоненте. Изменения состояния автоматически отражаются в DOM через реактивные переменные.
  • Неуправляемые элементы — напрямую работают с DOM через ref и стандартные методы (focus(), blur()).

Пример управляемого ввода с автофокусом:

<controlled-input>
  <input type="text" bind={this.value}>
  <script>
    this.value = ''
    this.on('mount', () => this.refs.inputField.focus())
  </script>
</controlled-input>

Использование реактивного биндинга обеспечивает синхронизацию состояния с интерфейсом и упрощает управление фокусом при динамических изменениях данных.


Переключение фокуса между элементами

Для реализации клавиатурной навигации можно использовать массив refs или стандартные селекторы querySelectorAll. Управление фокусом осуществляется через методы focus() и blur(), а события клавиатуры (keydown, keyup) позволяют определить направление перемещения.

Пример циклического перемещения фокуса по кнопкам:

<focus-cycle>
  <button ref="btn1">Кнопка 1</button>
  <button ref="btn2">Кнопка 2</button>
  <button ref="btn3">Кнопка 3</button>
  <script>
    this.refsArray = [this.refs.btn1, this.refs.btn2, this.refs.btn3]
    this.on('mount', () => {
      let index = 0
      this.refsArray[index].focus()

      this.root.addEventListener('keydown', e => {
        if(e.key === 'ArrowRight') {
          this.refsArray[index].blur()
          index = (index + 1) % this.refsArray.length
          this.refsArray[index].focus()
        }
      })
    })
  </script>
</focus-cycle>

Такой подход позволяет создавать доступные интерфейсы с поддержкой клавиатурной навигации.


Доступность (Accessibility) в Riot.js

Для обеспечения доступности компонентов важно использовать стандартные ARIA-атрибуты и корректную семантику HTML. Riot.js не ограничивает использование этих атрибутов, а реактивность упрощает их динамическое обновление.

Примеры применения ARIA:

<accordion>
  <button 
    aria-expanded={this.open} 
    aria-controls="panel1" 
    oncl ick={toggle}>Развернуть</button>
  <div id="panel1" hidden={!this.open}>
    Контент панели
  </div>
  <script>
    this.open = false
    const toggle = () => this.open = !this.open
  </script>
</accordion>

Обновление атрибутов при изменении состояния гарантирует совместимость с экранными читалками и другими средствами доступности.


Обработка событий фокуса

Riot.js поддерживает стандартные события focus и blur, а также их синтаксический сахар через on:. Это позволяет создавать сложные сценарии взаимодействия с элементами, включая визуальные эффекты и валидацию.

Пример динамического подсвечивания элемента при фокусе:

<input 
  type="text" 
  ref="inputField" 
  on:focus={() => this.active = true} 
  on:blur={() => this.active = false}
  class={this.active ? 'highlight' : ''}>
<script>
  this.active = false
</script>

Такой подход позволяет отделять логику управления состоянием фокуса от визуального оформления, сохраняя чистую архитектуру компонентов.


Автоматизация фокуса при динамическом рендере

При создании списков и динамических форм важно правильно управлять моментом установки фокуса. Riot.js предоставляет события жизненного цикла mount и updated, которые позволяют безопасно применять методы фокуса после обновления DOM.

Пример автофокуса на последнем элементе списка:

<item-list>
  <ul>
    <li each={item, i in items} ref={'item' + i}>{item}</li>
  </ul>
  <script>
    this.items = ['Элемент 1', 'Элемент 2', 'Элемент 3']
    this.on('updated', () => {
      const lastIndex = this.items.length - 1
      this.refs['item' + lastIndex].focus()
    })
  </script>
</item-list>

Использование updated предотвращает ошибки, связанные с попыткой сфокусироваться на еще не существующем элементе.


Практические рекомендации

  • Использовать ref для прямого доступа к элементам, требующим фокуса.
  • Применять реактивные переменные для синхронизации состояния с DOM.
  • Включать ARIA-атрибуты и поддерживать правильную семантику HTML.
  • Обрабатывать события focus и blur для динамических интерфейсов.
  • Использовать события жизненного цикла mount и updated для корректного управления фокусом при динамическом рендере.

Такой подход обеспечивает создание доступных, интерактивных компонентов с гибким управлением фокусом и поддержкой клавиатурной навигации.