Haunted — это библиотека для создания веб-компонентов на базе хуков, аналогичных React. При работе со сложными формами ключевыми являются управляемые состояния, валидация данных и эффективная обработка событий. Использование Haunted позволяет легко объединять эти элементы, обеспечивая реактивность и модульность кода.
В Haunted состояния создаются с помощью хука useState.
Для сложной формы рекомендуется хранить все поля в одном объекте
состояния:
import { component, useState } from 'haunted';
import { html } from 'lit-html';
function ComplexForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
password: '',
preferences: {
newsletter: false,
notifications: true
}
});
const handleChange = (e) => {
const { name, value, type, checked } = e.target;
if (type === 'checkbox') {
setFormData(prev => ({
...prev,
preferences: {
...prev.preferences,
[name]: checked
}
}));
} else {
setFormData(prev => ({ ...prev, [name]: value }));
}
};
return html`
<form>
<input name="name" .value=${formData.name} @input=${handleChange} placeholder="Имя">
<input name="email" .value=${formData.email} @input=${handleChange} placeholder="Email">
<input name="password" type="password" .value=${formData.password} @input=${handleChange} placeholder="Пароль">
<label>
<input type="checkbox" name="newsletter" .checked=${formData.preferences.newsletter} @change=${handleChange}>
Подписка на новости
</label>
<label>
<input type="checkbox" name="notifications" .checked=${formData.preferences.notifications} @change=${handleChange}>
Уведомления
</label>
</form>
`;
}
customElements.define('complex-form', component(ComplexForm));
Особенности подхода:
formData.type === 'checkbox'.setFormData, что
сохраняет реактивность интерфейса.Haunted не предоставляет встроенной системы валидации, но легко интегрируется с кастомными функциями. Валидация может выполняться на лету или при отправке формы:
const validateForm = (data) => {
const errors = {};
if (!data.name) errors.name = 'Имя обязательно';
if (!/\S+@\S+\.\S+/.test(data.email)) errors.email = 'Неверный email';
if (data.password.length < 6) errors.password = 'Пароль слишком короткий';
return errors;
};
const [errors, setErrors] = useState({});
const handleSubmit = (e) => {
e.preventDefault();
const validationErrors = validateForm(formData);
setErrors(validationErrors);
if (Object.keys(validationErrors).length === 0) {
console.log('Форма корректна', formData);
}
};
Рекомендации:
Object.keys(errors).length удобно для
проверки полного прохождения валидации.Сложные формы часто содержат динамические элементы, например, список контактов, который пользователь может расширять:
const [contacts, setContacts] = useState([{ type: 'email', value: '' }]);
const addContact = () => {
setContacts([...contacts, { type: 'email', value: '' }]);
};
const updateContact = (index, newValue) => {
const updated = contacts.map((c, i) => i === index ? { ...c, value: newValue } : c);
setContacts(updated);
};
html`
<div>
${contacts.map((contact, i) => html`
<input .value=${contact.value} @input=${e => updateContact(i, e.target.value)}>
`)}
<button type="button" @click=${addContact}>Добавить контакт</button>
</div>
`;
Ключевые моменты:
map,
что сохраняет иммутабельность.Для сложных форм полезно отслеживать изменения состояния и выполнять
побочные эффекты. В Haunted используется useEffect:
import { useEffect } from 'haunted';
useEffect(() => {
console.log('Форма изменилась:', formData);
}, [formData]);
Применения эффекта:
Haunted легко работает с другими веб-компонентами. Например,
использование кастомного date-picker:
html`
<date-picker
.value=${formData.birthDate}
@change=${e => setFormData({...formData, birthDate: e.target.value})}>
</date-picker>
`;
Особенности:
.value.@change) интегрируются с состоянием
формы.Haunted автоматически повторно рендерит компонент при изменении состояния. Для сложных форм важно минимизировать лишние обновления:
useEffect с конкретными
зависимостями, чтобы избегать ненужных вызовов.html шаблоны с повторяющимися элементами
через map, сохраняя ключи для идентификации.Формы часто требуют отправки данных на сервер. В Haunted это делается через стандартные промисы и async/await:
const submitForm = async (e) => {
e.preventDefault();
const validationErrors = validateForm(formData);
setErrors(validationErrors);
if (Object.keys(validationErrors).length === 0) {
try {
const response = await fetch('/api/submit', {
method: 'POST',
body: JSON.stringify(formData),
headers: { 'Content-Type': 'application/json' }
});
const result = await response.json();
console.log('Ответ сервера:', result);
} catch (err) {
console.error('Ошибка отправки формы:', err);
}
}
};
Особенности:
Haunted предоставляет гибкий и мощный инструмент для построения сложных форм, объединяя реактивное состояние, динамические поля, валидацию и эффекты, при этом сохраняя чистоту и модульность кода.