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

Ember.js предлагает мощный механизм обработки событий, позволяя легко работать с пользовательским взаимодействием, таких как клики, изменения формы, перемещения мыши и другие события. Обработчики событий играют ключевую роль в создании интерактивных веб-приложений. В Ember.js действия (actions) привязываются к элементам DOM и управляют логикой приложения.

Определение действий

В Ember.js действия реализуются как методы внутри компонентов или контроллеров. Обычно действия обрабатываются в контексте определённого компонента, маршрута или контроллера, где они могут быть переданы представлению для привязки к событиям.

Пример объявления действия в компоненте:

import Component from '@glimmer/component';

export default class MyComponent extends Component {
  // Объявление действия
  handleClick() {
    console.log('Кнопка была нажата');
  }
}

Привязка событий к действиям

Для привязки события в шаблоне к действию используется хелпер {{on}}. Этот хелпер обеспечивает связь между пользовательским взаимодействием и методом компонента.

Пример использования {{on}} в шаблоне компонента:

<button {{on 'click' this.handleClick}}>Нажми меня</button>

В данном примере событие click на кнопке будет вызывать метод handleClick компонента.

Передача аргументов в действия

Если необходимо передать дополнительные данные в действие, это можно сделать через аргументы хелпера {{on}}. В Ember.js для этого используются дополнительные параметры внутри метода.

Пример передачи аргумента в действие:

import Component from '@glimmer/component';

export default class MyComponent extends Component {
  // Обработка клика с передачей данных
  handleClick(message) {
    console.log(message);
  }
}

Шаблон компонента:

<button {{on 'click' (fn this.handleClick 'Привет!')}}>Нажми меня</button>

В этом примере строка 'Привет!' передаётся как аргумент в метод handleClick.

События в компонентах и контроллерах

В Ember.js можно использовать действия как внутри компонентов, так и в контроллерах. Когда действие используется в контроллере, оно управляет состоянием или логикой, связанной с маршрутом или представлением.

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

import Controller from '@ember/controller';

export default class MyController extends Controller {
  // Действие для обработки клика
  handleClick() {
    alert('Кнопка была нажата');
  }
}

В шаблоне можно привязать это действие аналогично компоненту:

<button {{on 'click' this.handleClick}}>Нажми меня</button>

Использование действий в маршрутах

Маршруты в Ember.js также могут использовать действия для обработки событий, связанных с загрузкой данных или переходами между состояниями.

Пример действия в маршруте:

import Route from '@ember/routing/route';

export default class MyRoute extends Route {
  // Действие для обработки клика
  @action
  handleClick() {
    console.log('Клик в маршруте');
  }
}

В шаблоне маршрута можно использовать хелпер {{on}} для привязки:

<button {{on 'click' this.handleClick}}>Нажми меня</button>

Использование декоратора @action

В Ember.js можно использовать декоратор @action для более явного указания, что метод является действием. Это особенно полезно, когда нужно работать с асинхронными операциями или с состоянием компонента.

Пример использования декоратора @action:

import Component from '@glimmer/component';
import { action } from '@ember/object';

export default class MyComponent extends Component {
  @action
  handleClick() {
    console.log('Кнопка была нажата');
  }
}

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

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

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

Пример асинхронного действия:

import Component from '@glimmer/component';

export default class MyComponent extends Component {
  @action
  async handleClick() {
    const data = await fetch('/api/data');
    const json = await data.json();
    console.log(json);
  }
}

Этот код позволяет обработать клик на кнопке, асинхронно загрузив данные с сервера и выведя их в консоль.

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

Для управления состоянием в Ember.js можно использовать действия для изменения состояния компонентов или контроллеров. В Ember.js компоненты имеют состояние, которое можно изменять через действия, привязанные к событиям.

Пример изменения состояния компонента через действие:

import Component from '@glimmer/component';

export default class MyComponent extends Component {
  isVisible = false;

  @action
  toggleVisibility() {
    this.isVisible = !this.isVisible;
  }
}

В шаблоне компонента можно использовать состояние isVisible для динамического изменения видимости элемента:

<button {{on 'click' this.toggleVisibility}}>Показать/Скрыть</button>

{{#if this.isVisible}}
  <p>Этот текст видим!</p>
{{/if}}

Прерывание событий

Иногда необходимо предотвратить выполнение действия по умолчанию, например, отменить переход по ссылке или остановить распространение события. Для этого в Ember.js используется метод preventDefault и stopPropagation.

Пример прерывания события:

import Component from '@glimmer/component';

export default class MyComponent extends Component {
  @action
  handleClick(event) {
    event.preventDefault();
    event.stopPropagation();
    console.log('Клик был отменён');
  }
}

В этом примере событие клика будет отменено, и его распространение по дереву DOM будет остановлено.

Заключение

Обработчики событий в Ember.js предоставляют гибкий и мощный механизм для управления пользовательским взаимодействием. Использование хелпера {{on}} для привязки событий и действий, а также использование декоратора @action для явного указания действий, позволяют создавать чистые и поддерживаемые компоненты и контроллеры. Асинхронная обработка, управление состоянием и прерывание событий делают фреймворк ещё более удобным и функциональным инструментом для разработки современных веб-приложений.