Slim.js — это современная библиотека для создания компонент на
JavaScript, обеспечивающая лёгкую реактивность и декларативный
рендеринг. Одной из ключевых возможностей является работа с кастомными
событиями и передачей данных через объект event.detail.
event.detailВ DOM существует встроенный механизм событий через Event
и его наследников (CustomEvent, MouseEvent и
другие). Для передачи данных внутри событий в Slim.js используется
объект detail, доступный при создании
CustomEvent.
Пример создания и отправки события:
const event = new CustomEvent('user-selected', {
detail: { id: 42, name: 'Alice' },
bubbles: true,
composed: true
});
element.dispatchEvent(event);
Ключевые моменты:
detail может содержать любые данные: объекты, массивы,
примитивные типы.bubbles: true позволяет событию подниматься вверх по
DOM.composed: true позволяет событию выходить из Shadow
DOM.В Slim.js привязка обработчиков событий осуществляется через атрибут
@event, где event — имя события.
Пример компонента:
import { Slim, html } from 'slim-js';
class UserList extends Slim {
users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
selectUser(user) {
this.dispatchEvent(new CustomEvent('user-selected', {
detail: user,
bubbles: true,
composed: true
}));
}
render() {
return html`
<ul>
${this.users.map(user => html`
<li @click="${() => this.selectUser(user)}">${user.name}</li>
`)}
</ul>
`;
}
}
Slim.define('user-list', UserList);
Здесь event.detail автоматически содержит объект
user, переданный при вызове dispatchEvent.
event.detail в родительских компонентахКогда событие всплывает до родителя, данные можно извлечь через обработчик:
class AppRoot extends Slim {
handleUserSelected(event) {
console.log('Выбран пользователь:', event.detail);
}
render() {
return html`
<user-list @user-selected="${this.handleUserSelected}"></user-list>
`;
}
}
Slim.define('app-root', AppRoot);
Особенности:
event.detail всегда содержит именно те данные, которые
были переданы при CustomEvent.this с
компонентом, если обработчик объявлен как метод класса.event.detail часто используется для передачи состояния
из дочернего компонента в родительский.
Пример: выбор элемента списка, настройка формы, уведомление об изменении состояния.
Slim.js позволяет использовать event.detail внутри
шаблонов для динамического изменения интерфейса.
handleUserSelected(event) {
this.selectedUser = event.detail;
}
При этом selectedUser автоматически обновляет шаблон,
если используется в рендере.
В сложных интерфейсах одно событие может содержать несколько параметров, передаваемых через объект:
this.dispatchEvent(new CustomEvent('item-action', {
detail: { itemId: 5, action: 'delete' },
bubbles: true
}));
Родительский компонент извлекает нужные данные:
handleItemAction(event) {
const { itemId, action } = event.detail;
if(action === 'delete') {
this.deleteItem(itemId);
}
}
Если компонент использует Shadow DOM, composed: true в
CustomEvent делает событие доступным за пределами теневого
дерева:
const event = new CustomEvent('notify', {
detail: { message: 'Привет' },
bubbles: true,
composed: true
});
this.shadowRoot.dispatchEvent(event);
Без composed: true событие не поднимется за пределы
Shadow DOM.
event.detail в Slim.jsdetail, даже если
передаётся один параметр — это упрощает расширение события в
будущем.function dispatchUserSelected(el, user) {
el.dispatchEvent(new CustomEvent('user-selected', {
detail: user,
bubbles: true,
composed: true
}));
}
detail, чтобы упростить интеграцию
между разработчиками.event.detail уникален для CustomEvent и
отсутствует в стандартных событиях, таких как click или
input.@event, что сокращает boilerplate по сравнению с
addEventListener.detail делает события самодостаточными —
все данные передаются внутри события, без необходимости хранить
состояние в глобальных переменных.class FilterList extends Slim {
items = ['Apple', 'Banana', 'Orange'];
filterItems(query) {
const filtered = this.items.filter(item => item.toLowerCase().includes(query.toLowerCase()));
this.dispatchEvent(new CustomEvent('filter-applied', {
detail: { query, filtered },
bubbles: true
}));
}
render() {
return html`
<input type="text" @input="${e => this.filterItems(e.target.value)}" placeholder="Фильтр">
<ul>
${this.items.map(item => html`<li>${item}</li>`)}
</ul>
`;
}
}
Slim.define('filter-list', FilterList);
Родительский компонент может получить и использовать данные фильтрации:
handleFilter(event) {
console.log('Поиск:', event.detail.query);
console.log('Результаты:', event.detail.filtered);
}
event.detail является мощным инструментом для передачи
данных внутри приложения на Slim.js, обеспечивая декларативную
реактивность, гибкость в организации компонентов и простоту интеграции
между дочерними и родительскими элементами.