Функции сброса широко распространены в веб-приложениях. Поэтому стоит найти многоразовое решение, не впадая в сложности.

Описание проблемы

Предположим, вы человек, который, как и я, хочет начать писать небольшие блоги о технологиях. Но вместо того, чтобы использовать существующую платформу, вы хотите создать свою собственную. И вы хотите иметь веб-форму, которая позволит вам отправлять приглашения своим друзьям, чтобы они могли следить за вашими блогами. Вроде этого:

Как мы видим, в форме есть несколько полей о человеке, которого мы хотим пригласить, и некоторые настройки уведомлений. Кроме того, есть некоторые значения по умолчанию: частота уведомлений по умолчанию составляет две недели, а уведомления о контенте Frontend и Backend включены по умолчанию (давайте будем честными, большинство ваших друзей — разработчики). Чтобы отслеживать информацию формы, нам нужно определить реактивные свойства для каждого из полей в форме.

В предыдущем коде мы определили некоторые значения ref и reactive, привязанные к полям формы, и, кроме того, мы определили обратный вызов, используемый при отправке формы. Обратный вызов разворачивает значения и вызывает службу функции с данными, которые ввел пользователь — здесь ничего особенного, просто обычный способ создания формы и сохранения информации. Давайте посмотрим на это в действии.

Как видите, наша форма работает; однако не хватает одного последнего шага, и вы, вероятно, тоже это заметили. После отправки приглашения форма все еще содержит данные, которые мы недавно отправили, или, другими словами, компонент не сбрасывается в исходное состояние. Такого рода функции сброса широко распространены в веб-приложениях. Обычно с формами, предназначенными для многократного использования, например, с формой, которая добавляет новых пользователей в таблицу, или даже с диалоговыми окнами, которые содержат форму, которая, как ожидается, будет иметь чистое состояние каждый раз, когда открывается диалоговое окно. Поэтому стоит найти общее решение, позволяющее сбрасывать состояния компонентов, не впадая в сложности.

Кратко рассмотрим существующие решения и их недостатки.

Существующие решения и их недостатки

Императивный подход

Императивный подход предполагает ручной сброс каждого отдельного значения до исходного состояния.

Первая проблема этого подхода — ручной процесс сброса состояния. Разработчик всегда должен помнить о включении оператора сброса каждый раз, когда он добавляет новое поле в форму. Вторая проблема — это дублирование значений по умолчанию, которые должны быть как в инстанцировании реактивных значений, так и в функции сброса; этот последний вид зависимости известен как совпадение ценности. Мы могли бы избежать второй проблемы, удалив значения по умолчанию при создании экземпляров переменных и вызвав функцию resetState позже, но это потеряло бы неявный смысл начальных значений, которые должны быть определены при создании экземпляров переменных.

Уничтожить и создать компонент

Этот подход подразумевает воссоздание компонента с нуля со специальным атрибутом «key"», который алгоритм виртуального DOM Vue использует для идентификации VNodes при сравнении нового списка узлов со старым списком. В нескольких словах, атрибут «key» является своего рода идентификатором для VNodes, что означает, что если мы изменим его, скажем, с начального значения key="1" на key="2",, Vue идентифицирует компонент с key="2" как совершенно новый элемент, который появляется, поскольку он не находит VNode с идентификатором, равным 2, и, поскольку в новом списке VNodes нет элемента с key="1", он делает вывод, что должен удалить элемент DOM текущего элемента с key="1".. Это удаление и воссоздание в двух словах.

Поскольку определение атрибута «ключ» должно быть установлено родительским компонентом, который отображает компонент, который мы хотим воссоздать, этот подход подразумевает броски событий связи родитель-потомок.

Очевидным недостатком такого подхода является необходимость привлечения родительского компонента для достижения цели, особенно если разработчик хочет рассматривать форму как неуправляемый компонент. С другой стороны, если вы собираетесь рассматривать форму как управляемый компонент, вам придется поднимать состояние до родительского компонента, и тогда у нас все равно будет та же проблема, но в родительском. Подъем состояния переводит проблему с одного компонента на другой.

Новое решение

Мы можем создать функцию или функцию композиции, содержащую логику для сброса любого состояния компонента независимо от его формы и значений. А поскольку это всего лишь функция, мы можем легко повторно использовать ее в любом компоненте, не меняя лежащей в ее основе логики. Это просто «Подключи и работай».

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

Как я уже говорил, это просто «подключи и работай», как и должно быть для любого программного обеспечения, предназначенного для повторного использования. Мне не пришлось вообще менять текущую реализацию компонентов, и самое приятное то, что ее можно полностью использовать повторно вместе с любым компонентом. Вы можете передать любой вложенный объект или массивы, и он будет отслеживать любой экземпляр reactive/ref, чтобы впоследствии сбросить его значение.

API композиции открывает ворота к новому способу создания многократно используемых частей логических задач, и хотя это не новая идея, действительно стоит упомянуть фантастическую работу, которую команда Vue только что проделала для нас. Я призываю вас использовать эту функцию композиции и создавать другие, о которых вы еще не думали.

Ссылка Codesanbox с примерами кода.