Текстовые поля представляют собой сложную и деликатную проблему: как и где вы храните текст и как вы обновляете прослушиватели событий, когда происходит изменение.

Модель HTML заключается в простом хранении содержимого текстового поля в модели DOM и вызове прослушивателей обновлений всякий раз, когда запускается соответствующее событие. Эта модель проверена временем и хорошо работает с тем, как Javascript преобразует переменные в анонимные функции. Большинство языков программирования (за исключением функциональных) не ограничивают внешние переменные замыканиями. Решётка построена на Rust, у которого более-менее есть эта проблема.

«Проблема» View-State заключается в том, что при запуске события мы можем захотеть сослаться на обе переменные, которые были созданы 1) при создании текстового поля и 2) которые с тех пор были привязаны к компоненту представления. Это звучит тривиально с Javascript, однако для сравнения функции безопасности Rust в отношении времени жизни переменных не позволяют нам найти здесь простое решение.

Хранилище состояния HTML в DOM хранит информацию в самом компоненте представления. Назовем эту стратегию «привязка к левому краю». Альтернативой может быть хранение информации в среде, которая управляет слушателями и вызывает их. Назовем эту вторую стратегию «привязка к правой стороне». С этой точки зрения мы видим, что в HTML/JS данные распределяются между левой и правой сторонами. По сути, это идеальное решение проблемы View-State, однако теперь возникает вопрос: «Как мы можем сделать то же самое в Rust»?

Первое решение, которое прекрасно звучит, хотя и уродливо, состоит в том, чтобы скопировать подход Javascript. Чтобы поделиться переменной в Rust, мы можем поместить значение в ссылочную ячейку (Rc, RefCell, Box и т. д.) и получить и/или обновить значение как с левой, так и с правой стороны. Недостатком этого подхода является то, что клиентский код становится невероятно грязным и трудным для чтения; не говоря уже о том, что каждая общая переменная должна быть явно связана, развернута и изменена с использованием тупых правил владения и времени жизни. Возможно, этот подход станет проще в будущем Rust, однако сейчас, на мой взгляд, это слишком обременительно.

Второе решение, которое используется в Lattice, заключается в использовании ограниченного стиля FRP. Это означает, что состояние объекта сохраняется «рядом» с левой стороной, но не совсем в компоненте представления. Под управлением движка существует связанное значение для каждого компонента представления и каналов , на которые могут подписаться слушатели. Когда компонент хочет обновить свое состояние, он вызывает функцию установки состояния, встроенную в каждый компонент. Для каждого компонента может быть несколько связанных значений разных типов. Затем механизм проверяет, должен ли подписчик быть уведомлен об изменениях, и если да, то отправляет событие слушателю.

Таким образом, можно ссылаться на левостороннее и правостороннее состояние, используя механизм в качестве посредника. Владение состоянием передается посреднику, а компоненты и прослушиватели всегда получают заимствованные значения. Этот подход очень прост с точки зрения пользователя и на практике работает почти так же, как подход Javascript.

Я все еще надеюсь, что в будущем замыкания в Rust будут иметь больше опций и лучшие значения по умолчанию в отношении переменных области действия, но на данный момент существует множество обходных путей.