Action в контексте SvelteKit — это паттерн, позволяющий обрабатывать события взаимодействия пользователя с компонентами на уровне серверной логики, сохраняя реактивность фронтенда и обеспечивая согласованное управление состоянием. Основная идея заключается в том, что действие (например, сабмит формы или клик кнопки) можно привязать к функции, которая будет выполняться на сервере или в компоненте, а результат возвращать обратно в интерфейс без полного перезагрузки страницы.
Action в SvelteKit реализуется через директиву use:.
Общий вид подключения:
<script>
import { formAction } from '$lib/actions';
function handleSubmit(node) {
return formAction(node, async (data) => {
const response = await fetch('/api/submit', {
method: 'POST',
body: JSON.stringify(data),
});
return await response.json();
});
}
</script>
<form use:handleSubmit>
<input name="username" required />
<button type="submit">Отправить</button>
</form>
Ключевые моменты:
Асинхронные действия позволяют интегрировать серверную обработку с реактивным интерфейсом без потери производительности. Пример асинхронного Action:
<script>
import { writable } from 'svelte/store';
const status = writable('idle');
async function asyncAction(node) {
node.addEventListener('click', async () => {
status.set('loading');
try {
const res = await fetch('/api/data');
const json = await res.json();
status.set('success');
console.log(json);
} catch (err) {
status.set('error');
console.error(err);
}
});
}
</script>
<button use:asyncAction>Загрузить данные</button>
<p>{$status}</p>
Особенности:
writable для реактивного отображения
состояния действия.Для сложных интерфейсов с множественными событиями часто применяют декомпозицию Action. Каждое действие инкапсулируется в отдельную функцию, которая возвращает объект с обработчиками и состоянием:
<script>
function createCounterAction() {
let count = 0;
return (node) => {
const increment = () => {
count += 1;
node.textContent = `Счетчик: ${count}`;
};
node.addEventListener('click', increment);
return {
destroy() {
node.removeEventListener('click', increment);
}
};
};
}
</script>
<button use:createCounterAction>Нажми меня</button>
Преимущества:
destroy.В SvelteKit допустимо комбинировать несколько Actions на одном элементе, при этом порядок их выполнения может контролироваться через композицию функций:
<script>
function logAction(node) {
const handler = () => console.log('Клик выполнен');
node.addEventListener('click', handler);
return { destroy: () => node.removeEventListener('click', handler) };
}
function alertAction(node) {
const handler = () => alert('Действие сработало');
node.addEventListener('click', handler);
return { destroy: () => node.removeEventListener('click', handler) };
}
</script>
<button use:logAction use:alertAction>Кликни меня</button>
destroy позволяют корректно очищать ресурсы при
размонтировании компонента.Action-паттерны тесно связаны с формами, позволяя обрабатывать сабмит через серверные endpoints:
<script>
import { fail } from '@sveltejs/kit';
export const actions = {
default: async ({ request }) => {
const data = await request.formData();
const username = data.get('username');
if (!username) return fail(400, { missing: true });
// Дальнейшая обработка, например запись в базу данных
return { success: true, username };
}
};
</script>
<form method="post" use:enhance>
<input name="username" required />
<button type="submit">Отправить</button>
</form>
POST,
PUT, DELETE).fail, возвращаемый
SvelteKit.enhance или кастомным Action.destroy, если Action подписан на события.Action-паттерны в SvelteKit обеспечивают мощный механизм реактивного взаимодействия компонентов с серверной логикой, позволяя строить масштабируемые и управляемые интерфейсы с минимальными усилиями по синхронизации состояния и событий.