Двустороннее связывание данных (two-way data binding) является одним из ключевых механизмов, позволяющих синхронизировать состояние приложения с пользовательским интерфейсом. В Riot.js это реализуется через реактивные свойства компонентов и специальные директивы, обеспечивая автоматическое обновление модели при изменении данных в форме и обратное отражение этих изменений в интерфейсе.
value и директивы oninputДля работы с двусторонним связыванием в Riot.js чаще всего
применяется сочетание атрибута value и события
oninput. Например:
<input type="text" value={this.name} onin put={e => this.name = e.target.value}>
<p>Привет, {this.name}!</p>
Здесь происходит следующее:
value={this.name} устанавливает исходное значение поля из
свойства name компонента.oninput отслеживает ввод пользователя и обновляет значение
свойства this.name.this.name изменяется, Riot автоматически
перерендеривает все участки шаблона, где используется данное
свойство.Ключевой момент — обновление данных происходит не только при
взаимодействии пользователя с формой, но и при программном
изменении свойства this.name.
update()Riot.js использует реактивную модель, поэтому изменения в свойствах
компонента требуют вызова метода update(), если они
происходят вне стандартных событий. Пример:
this.name = 'Иван';
this.update();
Метод update() инициирует повторный рендеринг
компонента, гарантируя, что все привязанные элементы интерфейса
синхронизированы с текущим состоянием данных.
Двустороннее связывание не ограничивается простыми строками или числами. Можно синхронизировать формы с объектами и массивами. Например:
<input type="text" value={this.user.email} onin put={e => this.user.email = e.target.value}>
<input type="text" value={this.user.name} onin put={e => this.user.name = e.target.value}>
<p>Email: {this.user.email}, Имя: {this.user.name}</p>
При изменении любого поля соответствующее свойство объекта
обновляется, а интерфейс автоматически отражает текущее состояние
объекта user.
Для элементов <input type="checkbox"> и
<input type="radio"> подход аналогичен, но учитывает
специфику значений:
Чекбокс:
<input type="checkbox" checked={this.isSubscribed} oncha nge={e => this.isSubscribed = e.target.checked}>
<p>{this.isSubscribed ? 'Подписка активна' : 'Подписка не активна'}</p>
Радиокнопки:
<input type="radio" name="gender" value="male" checked={this.gender === 'male'} oncha nge={e => this.gender = e.target.value}>
<input type="radio" name="gender" value="female" checked={this.gender === 'female'} oncha nge={e => this.gender = e.target.value}>
<p>Выбран пол: {this.gender}</p>
Особенность заключается в том, что для чекбоксов используется
свойство checked, а для радиокнопок — комбинация
checked и сравнения с текущим значением.
ref для более чистого кодаRiot.js позволяет получать прямой доступ к DOM-элементам через
директиву ref, что упрощает работу с формами:
<input type="text" ref="username">
<button oncl ick={() => console.log(this.refs.username.value)}>Показать имя</button>
В сочетании с двусторонним связыванием это может использоваться для промежуточной обработки значений перед обновлением модели.
Двустороннее связывание эффективно работает и с динамическими списками. Например, редактируемый список задач:
<ul>
<li each={task, i in this.tasks}>
<input type="text" value={task.text} onin put={e => this.tasks[i].text = e.target.value}>
</li>
</ul>
При изменении текста любой задачи массив tasks
обновляется автоматически, а интерфейс всегда показывает актуальные
значения.
oninput вместо onchange для
мгновенного обновления данных при вводе.update(), если изменения происходят
программно.Двустороннее связывание в Riot.js сочетает простоту синтаксиса и мощь реактивной модели, позволяя создавать формы, которые всегда остаются синхронизированными с данными без лишнего кода.