Riot.js позволяет создавать динамические формы с использованием реактивного подхода, где данные автоматически синхронизируются с пользовательским интерфейсом. Основной принцип заключается в том, что каждое поле формы связывается с реактивным состоянием компонента, а любые изменения состояния мгновенно отражаются в интерфейсе.
В Riot.js компоненты могут содержать реактивные массивы и объекты, что делает динамическое добавление и удаление полей естественным процессом. Для работы с формами чаще всего используются массивы объектов, где каждый объект представляет одно поле или набор связанных полей.
<dynamic-form>
<form onsub mit={submitForm}>
<div each={field, index in fields}>
<input type="text" bind={field.value} placeholder={field.label}/>
<button type="button" oncl ick={() => removeField(index)}>Удалить</button>
</div>
<button type="button" oncl ick={addField}>Добавить поле</button>
<button type="submit">Отправить</button>
</form>
<script>
export default {
fields: [
{ label: 'Имя', value: '' },
{ label: 'Email', value: '' }
],
addField() {
this.fields = [...this.fields, { label: 'Новое поле', value: '' }];
},
removeField(index) {
this.fields = this.fields.filter((_, i) => i !== index);
},
submitForm(event) {
event.preventDefault();
console.log(this.fields);
}
}
</script>
</dynamic-form>
eacheach — ключевой инструмент для
динамического рендеринга списков полей. Он автоматически отслеживает
изменения массива и обновляет DOM без необходимости ручного управления
элементами.
push или создание нового массива с помощью
spread-оператора.bind обеспечивает синхронизацию поля с объектом в
массиве.Важно помнить, что каждое поле должно иметь уникальный ключ, если используется сложная логика с вложенными компонентами, чтобы Riot корректно отслеживал изменения.
Динамические формы часто требуют валидации. Riot.js позволяет хранить ошибки в отдельном объекте и привязывать их к полям.
<dynamic-form>
<form onsub mit={submitForm}>
<div each={field, index in fields}>
<input type="text" bind={field.value} placeholder={field.label}/>
<span if={errors[index]} class="error">{errors[index]}</span>
<button type="button" oncl ick={() => removeField(index)}>Удалить</button>
</div>
<button type="button" oncl ick={addField}>Добавить поле</button>
<button type="submit">Отправить</button>
</form>
<script>
export default {
fields: [{ label: 'Имя', value: '' }],
errors: [],
addField() {
this.fields = [...this.fields, { label: 'Новое поле', value: '' }];
this.errors.push('');
},
removeField(index) {
this.fields = this.fields.filter((_, i) => i !== index);
this.errors = this.errors.filter((_, i) => i !== index);
},
validate() {
this.errors = this.fields.map(f => !f.value ? 'Поле обязательно' : '');
return !this.errors.some(Boolean);
},
submitForm(event) {
event.preventDefault();
if (this.validate()) {
console.log('Форма отправлена', this.fields);
}
}
}
</script>
</dynamic-form>
Для сложных интерфейсов можно создавать вложенные компоненты с собственными динамическими полями. В Riot.js это реализуется через импорт дочернего компонента и использование его в шаблоне родителя. Такой подход обеспечивает модульность и повторное использование компонентов.
<child-field>
<input type="text" bind={value}/>
<script>
export default { value: '' }
</script>
</child-field>
<parent-form>
<child-field each={field, index in fields}></child-field>
<button type="button" oncl ick={addChild}>Добавить дочернее поле</button>
<script>
import ChildField from './child-field.riot'
export default {
fields: [{}],
addChild() {
this.fields = [...this.fields, {}];
}
}
</script>
</parent-form>
При работе с большими формами важно оптимизировать обновления DOM:
spread, slice) для массивов и объектов, чтобы
Riot корректно отслеживал изменения.if для скрытия или
отображения полей вместо удаления их из DOM, если планируется повторное
использование.each для динамического рендеринга списка
полей.Динамические формы в Riot.js строятся вокруг реактивного состояния и автоматического синхронизированного рендеринга. Такой подход упрощает добавление, удаление и изменение полей, обеспечивая чистую и поддерживаемую архитектуру.