SkateJS — это легковесная библиотека для создания веб-компонентов с использованием чистого JavaScript. Одним из частых сценариев является работа с формами: отправка данных, управление состоянием полей, обработка событий и интеграция с внешними API. SkateJS предоставляет удобные механизмы для построения декларативных компонентов форм, поддерживая реактивные свойства и события.
Форма в SkateJS реализуется как веб-компонент с собственным классом.
Для этого используется функция define из SkateJS:
import { define, Component, h } from 'skatejs';
class UserForm extends Component {
static get props() {
return {
username: { attribute: true },
email: { attribute: true },
submitted: { type: Boolean }
};
}
handleSubmit(event) {
event.preventDefault();
this.submitted = true;
console.log('Отправка данных:', {
username: this.username,
email: this.email
});
}
render() {
return (
<form onSub mit={this.handleSubmit.bind(this)}>
<label>
Имя:
<input type="text" value={this.username} onIn put={e => this.username = e.target.value} />
</label>
<label>
Email:
<input type="email" value={this.email} onIn put={e => this.email = e.target.value} />
</label>
<button type="submit">Отправить</button>
{this.submitted && <p>Форма отправлена</p>}
</form>
);
}
}
define('user-form', UserForm);
Ключевые моменты:
props) автоматически
синхронизируются с атрибутами HTML.onInput позволяет реактивно обновлять состояние
полей.handleSubmit предотвращает стандартное поведение
формы и реализует кастомную логику отправки.SkateJS позволяет использовать реактивные свойства для управления состоянием. Каждое изменение свойства автоматически инициирует повторный рендер компонента. Это удобно для валидации и динамического отображения сообщений об ошибках:
static get props() {
return {
username: { attribute: true },
email: { attribute: true },
errors: { type: Object, default: () => ({}) }
};
}
validate() {
const errors = {};
if (!this.username) errors.username = 'Имя обязательно';
if (!this.email) errors.email = 'Email обязателен';
this.errors = errors;
return Object.keys(errors).length === 0;
}
handleSubmit(event) {
event.preventDefault();
if (this.validate()) {
console.log('Данные корректны:', { username: this.username, email: this.email });
}
}
Особенности подхода:
errors позволяет централизованно
управлять состоянием ошибок.errors приводит к обновлению
UI без дополнительных вызовов.SkateJS поддерживает стандартные события DOM, а также позволяет создавать кастомные события для коммуникации между компонентами:
handleSubmit(event) {
event.preventDefault();
if (this.validate()) {
this.dispatchEvent(new CustomEvent('form-submitted', {
detail: { username: this.username, email: this.email },
bubbles: true,
composed: true
}));
}
}
Важно:
bubbles: true позволяет событию подниматься по дереву
DOM.composed: true обеспечивает прохождение события через
shadow DOM, если компонент использует изоляцию.Отправка формы на сервер обычно требует работы с fetch
или другой библиотекой HTTP-запросов:
async handleSubmit(event) {
event.preventDefault();
if (!this.validate()) return;
try {
const response = await fetch('/api/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: this.username, email: this.email })
});
if (!response.ok) throw new Error('Ошибка при отправке данных');
const result = await response.json();
console.log('Ответ сервера:', result);
this.submitted = true;
} catch (err) {
this.errors.submit = err.message;
}
}
Рекомендации:
SkateJS позволяет создавать формы с динамическим количеством полей. Для этого удобно использовать массивы и методы массива:
static get props() {
return {
items: { type: Array, default: () => [''] }
};
}
addItem() {
this.items = [...this.items, ''];
}
updateItem(index, value) {
const newItems = [...this.items];
newItems[index] = value;
this.items = newItems;
}
render() {
return (
<form onSub mit={this.handleSubmit.bind(this)}>
{this.items.map((item, index) => (
<input
key={index}
value={item}
onIn put={e => this.updateItem(index, e.target.value)}
/>
))}
<button type="button" onCl ick={() => this.addItem()}>Добавить поле</button>
<button type="submit">Отправить</button>
</form>
);
}
Преимущества такого подхода:
key предотвращает ненужный пересоздание
элементов.SkateJS позволяет объединять визуальную часть и логику валидации внутри компонента. Это дает преимущества по поддержке и повторному использованию:
validateField(name, value) {
switch(name) {
case 'username':
return value.length > 0 ? '' : 'Имя обязательно';
case 'email':
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) ? '' : 'Некорректный email';
}
}
onInputChange(name, value) {
this[name] = value;
const error = this.validateField(name, value);
this.errors = { ...this.errors, [name]: error };
}
Особенности:
validateField делает
код чистым и поддерживаемым.Ошибки можно отображать напрямую в шаблоне:
<label>
Email:
<input type="email" value={this.email} onIn put={e => this.onInputChange('email', e.target.value)} />
{this.errors.email && <span class="error">{this.errors.email}</span>}
</label>
Преимущества:
errors.email.SkateJS обеспечивает изоляцию состояния компонентов. Несколько форм одного типа могут существовать на странице без конфликтов:
<user-form></user-form>
<user-form></user-form>
Каждый компонент имеет собственный экземпляр состояния
(props) и не зависит от других.
Для передачи данных из формы в родительские компоненты удобно использовать кастомные события:
this.dispatchEvent(new CustomEvent('user-data', {
detail: { username: this.username, email: this.email },
bubbles: true,
composed: true
}));
Это позволяет строить сложные интерфейсы, где родительская логика не вмешивается в внутреннее состояние формы.
errors.fetch с обработкой
ошибок.Такой подход обеспечивает высокую гибкость, чистоту кода и возможность расширения форм без дублирования логики.