Обработка пользовательского ввода в Hyperapp строится вокруг однонаправленного потока данных: событие → действие → изменение состояния → перерисовка интерфейса. В отличие от фреймворков с двусторонним связыванием, Hyperapp использует явную передачу данных через действия, что упрощает контроль над состоянием и делает поведение приложения предсказуемым.
Основными элементами механизма ввода являются:
Каждое пользовательское действие — клик, ввод текста, изменение фокуса — обрабатывается через событие DOM, связанное с конкретным действием Hyperapp.
В Hyperapp события DOM указываются непосредственно в JSX или
h()-вызовах. Вместо передачи callback-функций используются
действия, которые автоматически получают событие или
полезную нагрузку.
Пример обработки клика:
const state = { count: 0 }
const actions = {
increment: state => ({ count: state.count + 1 })
}
const view = (state, actions) =>
h("button", { onclick: actions.increment }, state.count)
В этом примере:
onclick связан напрямую с
actions.increment;Большинство событий ввода содержат полезные данные: текстовое значение, состояние чекбокса, выбранный элемент. Hyperapp передаёт объект события в действие, если оно ожидает аргумент.
const actions = {
setValue: (state, event) => ({
value: event.target.value
})
}
Привязка в представлении:
h("input", {
type: "text",
value: state.value,
oninput: actions.setValue
})
Здесь event.target.value извлекается напрямую внутри
действия, без промежуточных обработчиков.
Hyperapp использует управляемые компоненты, где значение элемента формы всегда синхронизировано с состоянием.
Текстовое поле:
const state = { text: "" }
const actions = {
updateText: (state, e) => ({ text: e.target.value })
}
const view = (state, actions) =>
h("input", {
value: state.text,
oninput: actions.updateText
})
Ключевые свойства:
value берётся из состояния;Для элементов с логическим состоянием используется
checked:
const state = { enabled: false }
const actions = {
toggle: (state, e) => ({ enabled: e.target.checked })
}
const view = (state, actions) =>
h("input", {
type: "checkbox",
checked: state.enabled,
onchange: actions.toggle
})
Событие onchange предпочтительнее для чекбоксов, так как
отражает окончательное состояние элемента.
Выпадающие списки обрабатываются аналогично текстовым полям:
const state = { color: "red" }
const actions = {
selectColor: (state, e) => ({ color: e.target.value })
}
const view = (state, actions) =>
h("select", { onchange: actions.selectColor, value: state.color }, [
h("option", { value: "red" }, "Red"),
h("option", { value: "green" }, "Green"),
h("option", { value: "blue" }, "Blue")
])
Значение select полностью определяется состоянием, что
исключает рассинхронизацию.
Иногда требуется передать в действие не объект события, а конкретное значение. Для этого используется частичное применение:
const actions = {
removeItem: (state, id) => ({
items: state.items.filter(item => item.id !== id)
})
}
Привязка:
h("button", {
onclick: () => actions.removeItem(item.id)
}, "Удалить")
Такой подход отделяет данные от DOM-события и повышает читаемость логики.
Для событий вроде отправки формы требуется отмена стандартного действия браузера. Это делается внутри действия:
const actions = {
submit: (state, e) => {
e.preventDefault()
return { submitted: true }
}
}
Использование:
h("form", { onsubmit: actions.submit }, [...])
Hyperapp не ограничивает доступ к объекту события, позволяя
использовать preventDefault, stopPropagation и
другие методы.
Сложные формы часто требуют нескольких действий: валидации, нормализации, отправки данных. Hyperapp поддерживает возврат функций из действий.
const actions = {
updateEmail: (state, e) => ({ email: e.target.value }),
submitForm: state => [
state,
(actions) => {
if (state.email.includes("@")) {
actions.send()
}
}
],
send: state => ({ sent: true })
}
Массив позволяет сначала обновить состояние, затем выполнить побочный эффект.
Валидация реализуется как часть действий или вычисляемых данных представления.
Пример простой проверки:
const state = {
password: "",
error: null
}
const actions = {
setPassword: (state, e) => {
const value = e.target.value
return {
password: value,
error: value.length < 6 ? "Слишком короткий пароль" : null
}
}
}
Отображение ошибки:
state.error && h("span", { class: "error" }, state.error)
Вся логика проверки сосредоточена в одном месте — действии.
Hyperapp поддерживает стандартные клавиатурные события:
const actions = {
handleKey: (state, e) => {
if (e.key === "Enter") {
return { submitted: true }
}
}
}
Использование:
h("input", { onkeydown: actions.handleKey })
Такой подход удобен для реализации горячих клавиш и управления с клавиатуры.
События onfocus и onblur используются для
управления состоянием интерфейса:
const state = { focused: false }
const actions = {
focus: () => ({ focused: true }),
blur: () => ({ focused: false })
}
const view = (state, actions) =>
h("input", {
onfocus: actions.focus,
onblur: actions.blur,
class: state.focused ? "active" : ""
})
Состояние фокуса становится частью общего состояния приложения.
Обработка пользовательского ввода в Hyperapp основана на следующих принципах:
Такой подход обеспечивает строгий контроль над поведением интерфейса и упрощает поддержку сложных сценариев взаимодействия.