Svelte
Привязки: bind:value, bind:this, `$bindable`
Поле ввода должно показывать текущее значение и менять его при наборе. Без привязки это два действия: подставить значение в атрибут и в обработчике oninput записать введённое обратно в состояние. Директива bind:value делает обе стороны разом - значение течёт в поле, а ввод течёт в состояние. Та же идея масштабируется выше: bind:this отдаёт ссылку на DOM-узел или экземпляр компонента, а руна `$bindable` помечает проп как доступный для двусторонней привязки из родителя.
- Поле формы: bind:value связывает input с состоянием, ввод сразу отражается в превью
- Чекбоксы и радио: bind:checked и bind:group для согласия и выбора варианта
- Фокус по кнопке: bind:this даёт ссылку на input, чтобы вызвать focus
- Видеоплеер: bind:this на элемент video для управления воспроизведением
- Компонент поля с собственной логикой, открывающий значение наружу через `$bindable`
Предварительные знания
- Реактивное состояние через `$state` и его изменение
- Чтение пропсов компонента через `$props`
- Понимание DOM-узла как объекта с методами вроде focus
bind:value на элементах формы
Директива bind:value связывает значение элемента формы с переменной в обе стороны. Изменение переменной обновляет элемент, а ввод пользователя обновляет переменную. Это убирает ручную пару из подстановки значения и обработчика oninput. Для разных элементов есть свои привязки: bind:checked для чекбокса, bind:group для радиокнопок и множественного выбора.
Привязка bind:value связывает поле name с состоянием: набор текста сразу обновляет приветствие. bind:checked отражает состояние чекбокса в булевой переменной. bind:group связывает группу радиокнопок с одной переменной, и выбранное value попадает в plan. Ни одного обработчика oninput писать не пришлось.
Привязка bind работает только с переменными, которые можно изменять. Связать с константой или с произвольным выражением нельзя - нужна переменная, в которую Svelte имеет право записать новое значение. Обычно это реактивное состояние через `$state`.
Что делает bind:value на текстовом поле ввода?
bind:this для ссылки на узел или экземпляр
Директива bind:this не связывает значение, а записывает в переменную ссылку на сам объект: DOM-узел для обычного элемента или экземпляр компонента. После монтирования переменная указывает на узел, и через неё можно вызвать его методы вроде focus или play. До монтирования значение пустое, поэтому обращаются к нему после того, как компонент появился на странице.
Переменная inputEl получает ссылку на реальный input после монтирования. Кнопка вызывает focusInput, и опциональная цепочка с вопросительным знаком защищает от обращения до того, как ссылка установлена. То же работает и с компонентом: bind:this на дочернем компоненте отдаёт его экземпляр, через который доступны экспортированные им функции.
- bind:value - значение — Связывает данные элемента с переменной в обе стороны. Применяется к полям ввода для синхронизации содержимого
- bind:this - ссылка — Записывает в переменную сам узел или экземпляр компонента. Нужен для императивных вызовов методов вроде focus или play
bind:this нужен для императивных действий, которые нельзя выразить декларативно: фокус, прокрутка к элементу, управление воспроизведением медиа, измерение размеров. Если задачу можно решить состоянием и разметкой, прямая ссылка на узел не нужна.
Что записывает в переменную директива bind:this на элементе input?
Двусторонний проп через `$bindable`
По умолчанию проп компонента односторонний: данные текут от родителя к ребёнку, и ребёнок не должен писать в проп напрямую. Иногда нужна двусторонняя связь - например, когда компонент поля ввода хочет отдавать введённое значение наверх. Руна `$bindable` помечает такой проп как доступный для привязки, и тогда родитель может использовать на компоненте директиву bind.
Внутри TextField проп value объявлен через `$bindable` со значением по умолчанию. Это разрешает писать в него и пробрасывать привязку дальше на input. Родитель использует bind:value на компоненте, и переменная email синхронизируется с тем, что введено внутри. Без `$bindable` такая привязка к пропу была бы запрещена.
Двусторонняя привязка к пропу - инструмент для случаев, когда дочерний компонент действительно владеет значением, как поле ввода. Для большинства взаимодействий поток данных вниз плюс callback наверх предсказуемее. Чрезмерное использование `$bindable` размывает направление потока и усложняет отладку.
Зачем объявлять проп через `$bindable`?
Связь с другими темами
Привязки соединяют состояние, DOM и пропсы компонента:
- `$state`: реактивное состояние — bind:value связывает поле ввода с реактивным состоянием
- `$props`: входные данные компонента — `$bindable` помечает проп как двусторонний
- События компонентов — Двусторонняя привязка решает ту же задачу синхронизации, что и callback наверх
Итог
- Директива bind связывает значение в обе стороны: состояние меняет элемент, а элемент меняет состояние
- bind:value для текстовых полей, bind:checked для чекбоксов, bind:group для радио и групп
- bind:this записывает в переменную ссылку на сам DOM-узел или экземпляр компонента
- Проп компонента по умолчанию односторонний; руна `$bindable` открывает к нему двустороннюю привязку
- Двусторонняя привязка применяется точечно - когда дочерний компонент действительно владеет значением
Связанные уроки
- sv-09-props — `$bindable` делает проп двусторонним, поэтому нужно понимание обычных пропсов через `$props`
- sv-06-state — Привязка связывает поле ввода с реактивным состоянием `$state`
- sv-13-component-events — Двусторонняя привязка - альтернатива callback-у, когда родителю важно лишь синхронизированное значение