Пользовательские события

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


Генерация пользовательских событий

Для генерации события используется метод $emit. Этот метод позволяет передавать название события и произвольные данные.

<my-button>
  <button oncl ick={handleClick}>Нажать</button>

  <script>
    function handleClick() {
      this.$emit('customClick', { message: 'Кнопка нажата' });
    }
  </script>
</my-button>

В примере выше компонент my-button при клике генерирует событие customClick с объектом данных { message: 'Кнопка нажата' }. Метод $emit может принимать несколько аргументов, которые будут переданы обработчику события.


Подписка на пользовательские события

Подписка на события осуществляется через атрибут on при использовании компонента:

<app>
  <my-button oncustomCl ick={handleCustomClick}></my-button>

  <script>
    import MyButton from './my-button.riot';

    export default {
      components: { MyButton },

      handleCustomClick(event) {
        console.log('Событие получено:', event.message);
      }
    }
  </script>
</app>

В этом примере компонент app получает событие customClick от дочернего компонента my-button и обрабатывает его через метод handleCustomClick. Все данные, переданные через $emit, доступны в обработчике события.


Пропуск событий через несколько уровней

Riot.js позволяет перехватывать события на промежуточных компонентах и при необходимости передавать их дальше. Это достигается использованием $emit внутри обработчика события:

<intermediate>
  <my-button oncustomCl ick={forwardEvent}></my-button>

  <script>
    function forwardEvent(data) {
      this.$emit('customClick', data);
    }
  </script>
</intermediate>

Таким образом, компонент intermediate получает событие от my-button и транслирует его дальше, позволяя родительскому компоненту app реагировать на событие без прямой связи с кнопкой.


Динамические и множественные события

Метод $emit не ограничен фиксированными именами событий. Название события может формироваться динамически:

this.$emit(`itemSelected:${item.id}`, item);

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


Отмена событий и одноразовые слушатели

Riot.js не имеет встроенного механизма отмены события (как stopPropagation в DOM), но можно контролировать обработку через флаги:

this.$emit('customClick', { stop: false });

function handleEvent(data) {
  if (!data.stop) {
    console.log('Обрабатываем событие');
  }
}

Для одноразового слушателя можно использовать флаг или вручную удалить обработчик после срабатывания.


Связь пользовательских событий с DOM-событиями

Пользовательские события легко интегрируются с нативными событиями DOM, что позволяет строить сложные взаимодействия между компонентами и элементами интерфейса:

<my-input>
  <input onin put={handleInput}>

  <script>
    function handleInput(e) {
      this.$emit('textChanged', e.target.value);
    }
  </script>
</my-input>

<app>
  <my-input ontextChan ged={updateText}></my-input>

  <script>
    function updateText(value) {
      console.log('Новый текст:', value);
    }
  </script>
</app>

Компонент my-input транслирует событие input в пользовательское событие textChanged, которое удобно использовать в родительском компоненте.


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

  • Пользовательские события помогают развязать компоненты, уменьшая зависимость от иерархии.
  • Названия событий должны быть описательными, чтобы сразу понимать их смысл.
  • Передача данных через события должна быть структурированной, предпочтительно в виде объектов.
  • Для компонентов коллекций и списков целесообразно использовать динамические имена событий, чтобы избежать путаницы.
  • Не использовать $emit для частых обновлений в высоконагруженных интерфейсах без необходимости, так как это может влиять на производительность.

Пользовательские события в Riot.js — это мощный инструмент для создания масштабируемых и модульных интерфейсов. Они обеспечивают чистую архитектуру, позволяют компонентам самостоятельно уведомлять о происходящих действиях и делают код более читаемым и поддерживаемым.