Функции сброса широко распространены в веб-приложениях. Поэтому стоит найти многоразовое решение, не впадая в сложности.
Описание проблемы
Предположим, вы человек, который, как и я, хочет начать писать небольшие блоги о технологиях. Но вместо того, чтобы использовать существующую платформу, вы хотите создать свою собственную. И вы хотите иметь веб-форму, которая позволит вам отправлять приглашения своим друзьям, чтобы они могли следить за вашими блогами. Вроде этого:
Как мы видим, в форме есть несколько полей о человеке, которого мы хотим пригласить, и некоторые настройки уведомлений. Кроме того, есть некоторые значения по умолчанию: частота уведомлений по умолчанию составляет две недели, а уведомления о контенте 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 с примерами кода.