Что такое управление состоянием?

Технически, каждый экземпляр компонента Vue уже «управляет» своим собственным реактивным состоянием. В качестве примера возьмем простой компонент счетчика
Это автономный блок, состоящий из следующих частей
  • Состояние — источник истины, который управляет нашим приложением
  • Представление , декларативное отображение состояния
  • Действия , возможные способы изменения состояния в ответ на действия пользователя из представления.
Это простое представление концепции «одностороннего потока данных»
Однако простота начинает нарушаться, когда у нас есть несколько компонентов, имеющих общее состояние
  • 1. Несколько представлений могут зависеть от одной и той же части состояния
  • 2. Действиям из разных представлений может потребоваться изменить одну и ту же часть состояния
В первом случае возможным обходным решением является «поднятие» общего состояния до общего компонента-предка, а затем передача его в качестве реквизита. Однако в деревьях компонентов с глубокой иерархией это быстро становится утомительным, что приводит к другой проблеме, известной как Prop Drilling
Во втором случае мы часто прибегаем к таким решениям, как обращение к прямым родительским/дочерним экземплярам через ссылки на шаблоны или попытки мутировать и синхронизировать несколько копий состояния через создаваемые события. Оба эти шаблона хрупкие и быстро приводят к неподдерживаемому коду
Более простое и понятное решение — извлечь общее состояние из компонентов и управлять им в глобальном синглтоне. Благодаря этому наше дерево компонентов становится большим «представлением», и любой компонент может получить доступ к состоянию или вызвать действия, независимо от того, где он находится в дереве

Простое управление состоянием с помощью Reactivity API

Если у вас есть часть состояния, которая должна использоваться несколькими экземплярами, вы можете использовать ее reactive() для создания реактивного объекта, а затем импортировать его в несколько компонентов
Теперь всякий раз, когда storeобъект мутирует, оба ComponentA объекта ComponentB автоматически обновляют свои представления — теперь у нас есть единый источник истины.
Однако это также означает, что любой импортируемый компонент store может изменять его по своему усмотрению
Хотя это работает в простых случаях, глобальное состояние, которое может быть произвольно изменено любым компонентом, в долгосрочной перспективе будет не очень удобно поддерживать. Чтобы гарантировать, что логика изменения состояния централизована, как и само состояние, рекомендуется определить в хранилище методы с именами, которые выражают цель действий
Обратите внимание
Обработчик кликов использует store.increment() круглые скобки — это необходимо для вызова метода с правильным this контекстом, поскольку это не метод компонента.
Хотя здесь мы используем один реактивный объект в качестве хранилища, вы также можете поделиться реактивным состоянием, созданным с помощью других API-интерфейсов реактивности, таких как ref() или computed(), или даже вернуть глобальное состояние из Composable
Тот факт, что система реактивности Vue отделена от модели компонентов, делает ее чрезвычайно гибкой

Соображения по реформе безопасности

Если вы создаете приложение, использующее серверный рендеринг (SSR) , приведенный выше шаблон может привести к проблемам, поскольку хранилище является одноэлементным, общим для нескольких запросов. Более подробно это обсуждается в следующей главе посвященной SSR

Pinia

Хотя нашего решения для управления состоянием вручную будет достаточно в простых сценариях, есть еще много вещей, которые следует учитывать в крупномасштабных производственных приложениях
  • Более строгие соглашения для командного сотрудничества
  • Интеграция с Vue DevTools, включая временную шкалу, внутрикомпонентную проверку и отладку с перемещением во времени.
  • Горячая замена модуля
  • Поддержка серверного рендеринга
Pinia — это библиотека управления состоянием, реализующая все вышеперечисленное. Он поддерживается основной командой Vue и работает как с Vue 2, так и с Vue 3.
Существующие пользователи могут быть знакомы с Vuex , предыдущей официальной библиотекой управления состоянием для Vue. Поскольку Pinia выполняет ту же роль в экосистеме, Vuex теперь находится в режиме обслуживания. Он по-прежнему работает, но новых функций больше не получит. Рекомендуется использовать Pinia для новых приложений.
Pinia начиналась как исследование того, как может выглядеть следующая итерация Vuex, включая множество идей из обсуждений основной команды Vuex 5. В конце концов мы поняли, что Pinia уже реализовала большую часть того, что мы хотели в Vuex 5, и решили сделать это вместо этого новая рекомендация.
По сравнению с Vuex, Pinia предоставляет более простой API с меньшими церемониями, предлагает API-интерфейсы в стиле Composition-API и, что наиболее важно, имеет надежную поддержку вывода типов при использовании с TypeScript.