Управление состоянием Vue (Vuex) для разработчиков React

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

Причина этой статьи

Почему я пишу эту статью? Что ж, весь мой опыт управления состоянием приложения в React был отрицательным, что неплохо, в то время как мне действительно нравится работать с Vuex. Я хочу поделиться тем, что, по моему мнению, является лучшим способом заявить о себе. Если у вас мало или совсем нет опыта работы с Vue и вы имеете опыт работы с React / Redux. Я надеюсь, вам понравится то, что я вам показал, и вы унесете положительное сообщение.

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

Состояние компонента в react нормальное, а для очень простого SPA, вероятно, требуется немного меньше кода, чем для Vue. Я по-прежнему расскажу о состоянии компонентов Vue, поскольку это неотъемлемая часть того, как состояние приложения интегрируется в компоненты.

Состояние приложения в React - это беспорядок, и на ум приходит «дикий запад» (успокойся, любовь моя, это всего лишь мое мнение), но я не извиняюсь за свою точку зрения. Вы как разработчик сами по себе. Вы должны сами выбрать государственный пакет, и каждый выбор сопряжен с компромиссами.

Есть несколько хороших моментов в управлении состоянием приложения в React, но эту статью стоит попробовать написать.

Что такое Vuex

Vuex - это пакет, используемый для управления состоянием приложения во Vue. Он поддерживается той же командой, которая поддерживает Vue, поэтому вам гарантирована совместимость. Vuex тесно связан с Vue, поэтому он спроектирован так, чтобы быть максимально простым и (я думаю) приятным в использовании. Эта плотная связь не мешает вам использовать redux, если вы действительно не заметите эти булавки в глазах :-).

Что охватывают мои примеры

  • Состояние компонента
  • Состояние приложения
  • Интеграция внешнего API в состояние компонента и приложения. (с использованием API SWAPI)
  • Постоянное состояние (состояние сохраняется после обновления браузера)

Полный код. Полный код этого руководства доступен на GitHub, поэтому вы можете быстро клонировать и экспериментировать. Https://github.com/simonjcarr/vue_state_for_react_developers

Состояние компонента

Компонент без состояния

Компонент во Vue может быть таким же простым, как код, показанный ниже, но у него не будет состояния.

Метод данных

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

Вычисляемые свойства

Добавить вычисляемые свойства в Vue так же просто, как экспортировать другое свойство, которое, как ни странно, называется computed.

Мы снова используем интерполяцию строк для вызова вычисляемого свойства addOne(), которое просто возвращает значение myNumber и добавляет к нему 1.

Методы

Мы можем делать более сложные вещи, такие как доступ к удаленным источникам данных с помощью методов. Следующий код немного сложнее, но я проведу вас по нему.

Прежде чем мы перейдем к коду, вот результат.

Так что здесь происходит?

Я добавил swPerson в data () и инициализировал его как null

Я создал новое свойство method на том же уровне, что и data и computed. Внутри свойства я добавил методgetPerson, который принимает одно свойство id. Метод использует fetch для подключения к swapi api с использованием переданного идентификатора и извлекает символ звездных войн. Он преобразует результат в JSON и сохраняет его в swPerson.

Я создал computed свойство personName. Он проверяет, является ли swPerson нулевым. Если он равен нулю, он просто возвращает ноль, если не ноль, он возвращает имя персонажа из «Звездных войн».

С указанным выше я смог обновить template, как показано ниже.

{{ personName }} - вычисляемое свойство. Как описано выше, он вернет либо null, либо имя персонажа звездных войн.

Я снова использую personName в кнопке, на этот раз используя директиву Vue. В этом случае директива v-if. v-if="!personName" говорит, что если personName имеет значение null, отобразить элемент, в данном случае это кнопка. Если он не равен нулю, кнопка должна быть скрыта. К кнопке также добавлен обработчик событий @click. Этот обработчик вызывает метод getPerson(1), передавая идентификатор символа, который мы хотим получить.

В сводке при нажатии кнопки getPerson получает данные из API SWAPI и обновляет swPerson. Это заставляет вычисляемое свойство personName обновлять модель DOM. Отображается имя персонажа, а кнопка скрывается. Надеюсь, вы согласитесь, что это действительно довольно элегантно.

В компонентах есть ряд других свойств, но я не собираюсь их здесь описывать. Если вам нужна более подробная информация, вы можете взглянуть на Компоненты Vue на веб-сайте Vue.

Состояние приложения

Теперь мы собираемся взглянуть на Vuex и на то, как он используется для управления состоянием на уровне приложения.

Это будет ускоряться по сравнению с простым состоянием компонента, которое мы видели выше, но я надеюсь, вы согласитесь, что это все еще относительно просто и приятно использовать.

Установка

Когда вы создаете новое приложение Vue с Vue create myapp, вам задают ряд вопросов о том, что вы хотите включить в приложение, Vuex - один из таких вариантов. Даже если вы не устанавливали Vuex при создании приложения, установить его позже будет очень просто.

Полные инструкции по установке можно найти здесь, но это просто

npm install vuex

Лучше всего создать в корне вашего приложения папку с именем store. Для простого управления состоянием нам нужен только один файл. По мере того, как ваше приложение становится больше, мы используем модули с каждым модулем в отдельном файле, поэтому лучше поместить файлы состояния в папку. Если вы выбрали Vuex при создании нового приложения с помощью Vue, эта папка уже будет существовать, а внутри находится файл index.js

Этот файл будет содержать всю конфигурацию состояния для простого приложения.

Вы увидите, что Vue и Vuex импортированы вверху файла.

Vue.use() - это то, что мы учим Vue делать что-то новое. Таким образом, Vue.use(Vuex), по сути, учит Vue всему, что ему нужно знать о Vuex.

Внизу файла создается и экспортируется новый экземпляр Vuex.store. Когда мы создаем новое хранилище, мы передаем конфигурацию, которая состоит из state, mutations, actions и modules. Если вы использовали redux, вы будете иметь хорошее представление о том, как они работают.

Конечно, Vue не знает, что этот файл существует, поэтому мы должны импортировать его в main.js, а затем указать нашему приложению использовать его. Я добавил комментарии к двум соответствующим строкам. Как я сказал выше, если вы использовали vue create xxxx для создания нового приложения, все это будет создано для вас.

Добавление состояния в Vuex

Я собираюсь создать очень простое приложение ToDo, которое хранит задачи todo во Vuex.

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

Я создам новый файл /store/todo.js

и импортировать в /store/index.js

Я прокомментировал две строки кода. Вот и все! наш новый модуль готов к использованию. Давайте создадим объект задачи и предварительно загрузим в него первую задачу.

In /store/todo.js

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

Я добавил 3 мутации. addTask, setTaskStatus, deleteTask

Здесь следует отметить несколько моментов.

Я импортировал lodash, чтобы помочь фильтровать задачи, uuid, чтобы создать идентификатор для каждой задачи.

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

В этом случае все, что мы делаем, это вызываем мутацию, однако действия действительно эффективны, когда они используются для вызовов внешнего API. Мы увидим это позже, когда извлечем еще несколько персонажей «Звездных войн» с помощью действий Vuex.

Магазин готов к использованию. Сейчас я покажу вам, как легко взаимодействовать с состоянием из компонента.

Компонент Todo

В файле /views/Todo.vue я начну со следующего базового кода.

Первым делом я привяжу состояние Vuex к компоненту. Мы делаем это с помощью помощника, предоставляемого Vuex mapState

Мы используем состояние карты в вычисляемом свойстве, например:

Я импортировал mapstate, а затем использовал оператор распространения ... для отображения состояния tasks из модуля Todo. Если бы в этом модуле было несколько состояний, я мог бы также включить их в массив. Если бы я хотел отобразить состояние другого модуля, я мог бы просто добавить еще ...mapState

Проделаем то же самое с действиями.

Вы увидите, что это действительно очень просто, с той лишь разницей, что наш сопоставленный Vuex actions был включен в свойство methods.

Создание шаблона

Все, что осталось сделать, это написать HTML-код для раздела шаблона компонентов и добавить некоторое локальное состояние для формы «Добавить задачу».

Вот Todos без формы, он позволяет нам работать с одним жестко запрограммированным делом, которое у нас есть. Мы можем удалить его и изменить его статус.

В приведенном выше коде я добавил кнопку для удаления задачи. Это вызывает метод deleteTask, который мы сопоставили, и передает task.id

Я создал еще одну кнопку для изменения полного статуса задачи. Он отправляет объект, содержащий id и status, которые мы хотим назначить задаче, когда событие \ @click запускается для setTaskStatus.

@click="setTaskStatus({ id: task.id, status: !task.complete })"

Я использую функцию Vue под названием v-bind с сокращением : для сопоставления динамических классов, а также устанавливаю правильный текст для кнопки на основе task.complete.

:class="{
'bg-green-500 text-white': !task.complete, 
'bg-red-500 text-white': task.complete
}"
{{ task.complete ? "Mark not Complete" : "Mark Complete" }}

Я также установил несколько стилей текста для заголовка задачи на основе task.complete.

:class="{ 'text-red-500 line-through': task.complete }"

Добавить новую форму задачи

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

Это полный комплект компонентов. У меня есть новое свойство newTask для data (), и я привязал ввод формы с помощью v-bind к newTask

Вы заметите, что форма использует \ @ submit.prevent, .prevent называется модификатором Vue, это избавляет нас от необходимости удерживать объект формы и вручную preventDefault. В любом случае, когда форма отправлена, вызывается метод theaddTaskSubmit. Это очередь вызывает addTask в Vuex и передает значение newTask

Как только Vuex обновляется, в нашем списке Todo отображается новая задача.

Доступ к удаленным данным с помощью Vuex

Мы почти закончили, я собираюсь показать вам кое-что, что не имеет смысла, но может показаться вам интересным.

Я добавлю свойство completedBy для каждой задачи, и когда задача будет помечена как завершенная, из SWAPI будет извлечен случайный персонаж из «Звездных войн», а поле имени будет использоваться для обновления completedBy.

Единственное, что нам нужно будет изменить в компоненте, - это добавить поле completedBy в список Todo. Я сделаю это первым

Сейчас буду обновлять /store/todo.js

Вы увидите, что я добавил новое свойство completedBy в tasks и включил его при создании новой задачи.

Когда задача обновлена, я просто вызвал fetch в SWAPI API, на этот раз передав случайное число от 1 до 10, и обновил поле compltedBy именем символа.

Сохраненное состояние Vuex

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

Я собираюсь установить модуль npm https://www.npmjs.com/package/vuex-persistedstate, который упростит это, это безумие.

В файл основного магазина /store/index.js вы его импортируете

import createPersistedState from 'vuex-persistedstate'

Затем добавьте новое свойство plugins и скажите Vuex загрузить его.

С этими двумя строками кода мы теперь можем обновить браузер и сохранить наше состояние.

Резюме

Надеюсь, вам понравилась эта статья. Это было намного дольше, чем я думал, но было довольно много того, что нужно было передать.

Целью статьи было показать разработчикам React, что может предложить Vue с точки зрения управления состоянием. Я надеюсь, что добился этого. Независимо от того, понравилась вам статья или нет, оставьте, пожалуйста, комментарий и дайте мне знать, что вы думаете.