Svelte
События компонентов: callback-пропсы
Компонент кнопки удаления должен сообщить родителю: 'элемент удалён, обнови список'. В Svelte 4 для этого заводили createEventDispatcher, создавали кастомное событие и слушали его через директиву on. Svelte 5 убрал лишний слой: родитель просто передаёт функцию onDelete как проп, а компонент вызывает её, когда нужно. Никакого диспетчера и кастомных событий - обработчик это обычная функция в пропсах, которую вызывают как любую другую. Та же идея и для DOM-событий: onclick стал обычным атрибутом.
- Кнопка с пропом onClick, которую родитель передаёт и обрабатывает по-своему
- Строка списка с onDelete: клик по корзине вызывает функцию родителя, та удаляет элемент
- Поле поиска с onSearch: компонент отдаёт введённый текст наверх через callback
- Модалка с onClose: при клике вне окна вызывается переданная функция закрытия
- Форма с onSubmit, которой родитель передаёт обработчик отправки с собранными данными
Предварительные знания
- Чтение пропсов через `$props` и передача значений в компонент
- JavaScript: функции как значения, передача функции в аргумент
- Понимание потока данных сверху вниз от родителя к ребёнку
Конец createEventDispatcher
В Svelte 4 компонент сообщал о событиях через createEventDispatcher: импорт функции, создание диспетчера, вызов dispatch с именем и данными, а родитель слушал через директиву on с именем события. Это был отдельный механизм, параллельный обычным пропсам. Svelte 5 признал его лишним: событие, о котором сообщает компонент, ничем по сути не отличается от вызова переданной функции. createEventDispatcher объявлен устаревшим, а каноничный способ - callback-пропсы. DOM-события тоже перешли на атрибуты: вместо директивы on:click пишут атрибут onclick.
Callback-пропсы вместо событий
Компонент принимает функцию через `$props`, как любой другой проп, и вызывает её, когда происходит нужное действие. Имя пропа по соглашению начинается с on: onClick, onDelete, onSubmit. Родитель передаёт свою функцию в этот проп, и при вызове внутри ребёнка управление переходит наверх. Данные о событии передаются аргументом вызова.
ListItem не знает, что делает родитель при удалении: он лишь вызывает onDelete с id элемента. Родитель передаёт функцию remove, которая фильтрует массив. Это обычный поток данных - функция спускается вниз как проп, а вызывается снизу вверх, передавая управление родителю.
Callback-проп можно сделать необязательным, задав значение по умолчанию: пустую функцию. Тогда вызов onDelete не упадёт, если родитель проп не передал. Это удобно для опциональных событий, которые слушать необязательно.
Как компонент в Svelte 5 сообщает родителю о произошедшем действии?
DOM-события как атрибуты
Обработчики DOM-событий в Svelte 5 задаются обычными атрибутами: onclick, oninput, onsubmit. Это не директива с двоеточием, как было раньше, а атрибут, в который кладут функцию. Такой синтаксис ближе к стандартным свойствам DOM и единообразен с callback-пропсами: и то и другое - просто функция в атрибуте.
- Svelte 4: директивы событий — Обработчик подключался директивой с двоеточием: on:click, on:input. Отдельный синтаксис, не похожий на обычные пропсы
- Svelte 5: атрибуты событий — Обработчик задаётся атрибутом: onclick, oninput. Тот же вид, что и callback-проп - функция в атрибуте
Модификаторы вроде preventDefault, которые в Svelte 4 писали после двоеточия, теперь делают внутри обработчика обычным кодом: вызывают event.preventDefault или event.stopPropagation. Это убрало особый синтаксис модификаторов в пользу обычного JavaScript.
Как в Svelte 5 подключают обработчик клика к элементу?
Всплытие через проброс callback-ов
Кастомные события Svelte 4 могли всплывать вверх по дереву компонентов через директиву on без обработчика - переадресацию события. С callback-пропсами автоматического всплытия нет, и это намеренно. Чтобы событие из глубокого компонента дошло до верхнего, каждый уровень явно пробрасывает callback дальше. Поток становится видимым: по коду понятно, кто и куда передаёт обработчик.
Компонент-список принимает onDelete от своего родителя и передаёт его каждому ListItem без изменений. Когда ListItem вызовет onDelete, обработка дойдёт до самого верхнего родителя. Промежуточный слой явно объявляет, что пробрасывает это событие, - неявной магии переадресации больше нет.
| Задача | Svelte 4 | Svelte 5 |
|---|---|---|
| Событие компонента | createEventDispatcher | callback-проп |
| DOM-событие | Директива on:click | Атрибут onclick |
| Переадресация | on без обработчика | Явный проброс пропа |
| Данные события | event.detail | Аргумент вызова |
Если компонент промежуточного уровня забыл пробросить callback дальше, событие не дойдёт до верха, и ошибки при этом не будет - функция просто не вызовется. Цепочку проброса проверяют по коду: каждый уровень между источником и обработчиком должен передавать проп.
Как событие из глубоко вложенного компонента доходит до верхнего родителя в Svelte 5?
Связь с другими темами
События строятся на пропсах и потоке данных:
- `$props`: входные данные компонента — Callback-проп - это обычный проп, значение которого функция
- Snippets — Как и сниппеты, обработчики передаются через пропсы
- Привязки и `$bindable` — Двусторонняя привязка - альтернатива callback-у для синхронизации значения
Итог
- Компонент сообщает родителю о событиях через callback-пропсы - обычные функции в пропсах
- Родитель передаёт функцию как проп, компонент вызывает её и при необходимости передаёт данные аргументом
- createEventDispatcher из Svelte 4 объявлен устаревшим, кастомные события больше не нужны
- DOM-события подключаются атрибутами вроде onclick вместо директивы on:click
- Прямого всплытия событий компонентов нет: чтобы передать событие выше, родитель пробрасывает callback дальше
Связанные уроки
- sv-09-props — Callback-проп - это обычный проп-функция, поэтому нужно знать чтение пропсов через `$props`
- sv-12-snippets — И обработчики, и сниппеты передаются через пропсы, заменяя прежние специальные API
- sv-14-bindings — Двусторонняя привязка через `$bindable` - альтернатива callback-у, когда родителю нужно лишь значение