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

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


События и свойства

В SkateJS события тесно связаны с реактивными свойствами компонентов. Свойства объявляются через объект props и могут автоматически реагировать на изменения:

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

class MyComponent extends Component {
  static get props() {
    return {
      counter: props.number()
    };
  }
}
define('my-component', MyComponent);

Изменение свойства counter можно отследить с помощью хука UPDATEd:

updated(prevProps) {
  if (prevProps.counter !== this.counter) {
    console.log(`Counter изменился: ${this.counter}`);
  }
}

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


Декларативные обработчики событий

SkateJS поддерживает декларативное привязывание обработчиков к DOM-элементам внутри компонента через метод render и JSX-подобный синтаксис:

render() {
  return (
    <button onCl ick={() => this.increment()}>Нажми меня</button>
  );
}

increment() {
  this.counter += 1;
}

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


Использование кастомных событий

SkateJS позволяет легко создавать и диспатчить пользовательские события, интегрируя их с внешними элементами:

increment() {
  this.counter += 1;
  this.dispatchEvent(new CustomEvent('counter-changed', {
    detail: { value: this.counter },
    bubbles: true,
    composed: true
  }));
}

Параметры bubbles и composed обеспечивают всплытие события и возможность его прохождения через shadow DOM. Это особенно важно при построении сложных компонентных иерархий.


Подписка на события внешних элементов

Обработка событий, инициируемых внешними DOM-элементами, осуществляется через стандартные методы addEventListener в сочетании с жизненным циклом SkateJS. Для корректного управления подписками рекомендуется использовать connectedCallback и disconnectedCallback:

connectedCallback() {
  super.connectedCallback();
  this.button = this.querySelector('button');
  this.button.addEventListener('click', this.handleClick);
}

disconnectedCallback() {
  this.button.removeEventListener('click', this.handleClick);
  super.disconnectedCallback();
}

handleClick = () => {
  console.log('Кнопка нажата');
};

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


Применение хуков SkateJS

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

  • updated — вызывается после обновления свойств или состояния компонента.
  • connected — вызывается при добавлении компонента в DOM.
  • disconnected — вызывается при удалении компонента из DOM.

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

connected() {
  this.addEventListener('mouseover', this.handleMouseOver);
}

disconnected() {
  this.removeEventListener('mouseover', this.handleMouseOver);
}

handleMouseOver = () => {
  console.log('Наведение на компонент');
};

Делегирование событий

Для элементов с большим числом потомков целесообразно использовать делегирование событий. SkateJS интегрируется с этой концепцией через обычные методы addEventListener:

this.addEventListener('click', (event) => {
  if (event.target.matches('li')) {
    console.log(`Нажат элемент списка: ${event.target.textContent}`);
  }
});

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


Комбинирование реактивности и событий

SkateJS позволяет связывать события с реактивными свойствами напрямую. Например, обновление свойства может инициировать событие:

static get props() {
  return {
    isActive: props.boolean({
      se t(isActive) {
        this.dispatchEvent(new CustomEvent('active-changed', {
          detail: { isActive },
          bubbles: true
        }));
        return isActive;
      }
    })
  };
}

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


Встроенные события жизненного цикла

Помимо пользовательских событий, SkateJS позволяет обрабатывать внутренние события компонентов. Хуки updated, rendered и connected можно использовать для реакции на изменения структуры DOM:

updated() {
  const input = this.shadowRoot.querySelector('input');
  if (input) {
    input.addEventListener('input', this.handleInput);
  }
}

Такой подход полезен для динамически создаваемых элементов и управления их состоянием через события.


SkateJS объединяет декларативную реактивность и гибкую систему событий, позволяя строить сложные компоненты с минимальными усилиями. Комбинация реактивных свойств, пользовательских событий и хуков жизненного цикла делает обработку событий безопасной, структурированной и удобной для масштабирования.