Vuex или Pinia. Что выбрать?

Сложно представить себе Vue-приложение, которое состоит из 1-2 компонентов. Обычно у нас есть десятки и даже сотни строительных блоков. Компоненты складываются в иерархическую структуру. Основной способ передать какие-либо данные с верхних уровней элементов к нижним – свойства компонентов. Для передачи чего-либо в обратном направлении обычно служат события. Однако, если какие-либо данные необходимо передавать через несколько уровней вложенности, то такой подход будет очень трудоемким. Скорее всего также, часть компонентов на пути передачи данных будут в этом лишь посредниками. То есть они будут получать данные, которые им самим не нужны. И это нарушает принципы SOLID. Такой подход станет еще более обременительным, если данные нужно передавать между соседними ветками иерархии.

Содержание

Передача данных между частями приложения

Есть различные варианты решения этой проблемы. Можно использовать provide/inject, EventBus (общую шину событий) и даже глобальный объект window. Но обычно в таких случаях последние годы разработчики использовали глобальное хранилище Vuex.

У Vuex есть реактивное состояние, которое можно делать доступным в любом компоненте, а также есть mutators для его изменения, а также actions для более высокоуровневых операций (часто асинхронных). Последняя особенность (наличие двух мест описания методов изменения состояния), кстати, доставляет не мало неудобств и вносит путаницу. У Vuex на протяжении долгого времени были проблемы, которые разработчики пытались решить вплоть до версии 4.

Pinia или Vuex 5?

В последнее время все чаще информационном пространстве появляются упоминания о Pinia, новой и перспективной библиотеке для реализации глобального состояния Vue-приложения. Она была создана Eduardo San Martin Morote как попытка получить понимание того, как должен выглядеть Vuex. Сначала это была просто библиотека, которую вы могли бы установить самостоятельно. Но 7 февраля 2022 года она стала частью экосистемы Vue и превратилась в рекомендуемую библиотеку для реализации глобального состояния приложения. Вы можете добавить ее через Vue CLI при создании нового приложения.

Но ведь в команде Vue велась работа над Vuex 5. Может быть он скоро выйдет и можно будет продолжать использовать Vuex, только с решенными проблемами? Вот что написано в README.md пакета Vuex:

The official state management library for Vue has changed to Pinia. Pinia has almost the exact same or enhanced API as Vuex 5, described in Vuex 5 RFC. You could simply consider Pinia as Vuex 5 with a different name. Pinia also works with Vue 2.x as well.

И так, у Pinia почти то же самое (или даже лучше) API как Vuex 5, описанного в документе Vuex 5 RFC . Вы можете просто думать о Pinia как о Vuex 5 с другим именем. Таким образом, не стоит ждать новой версии Vuex, а можно спокойно переходить на использование Pinia. В старых проектах, конечно придется много переписать при этом. Но Pinia и Vuex можно использовать одновременно и проводить миграцию постепенно.

Преимущества и отличия Pinia

С новой библиотекой разрабатывать становится удобнее. Pinia не такая многословная как Vuex. Можно выделить следующие преимущества:

  • Нет деления на mutators и actions. Теперь для изменения состояния нужны только actions
  • При изменении состояния не нужно обращаться к commit и dispatch , а можно вызывать нужный action по имени как метод
  • Лучшая поддержка TypeScript. Не требуется применения дополнительных трюков для этого.
  • Вместо модулей Vuex используется создание нескольких хранилищ Pinia для разных частей предметной области

Пример кода

Вот пример простого хранилища и его использования:

// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => {
    return { count: 0 }
  },
  actions: {
    increment() {
      this.count++
    },
  },
})
<script setup>
import { useCounterStore } from '@/stores/counter'

// Подключаем хранилище
const counter = useCounterStore()

counter.count++
// Вариант изменения данных (с автодополнением в IDE)
counter.$patch({ count: counter.count + 1 })
// или лучше использовать вариант с вызовом действия
counter.increment()
</script>

<template>
  <!-- Доступ к данным хранилища из шаблона -->
  <div>Current Count: {{ counter.count }}</div>
</template>

Это Composition API. И как легко догадаться, можно иметь несколько хранилищ с разным назначением (для каждой части предметной области, где это нужно) и импортировать требуемые по надобности.

Больше промеров можно найти в документации Pinia.

Плагины

Как и для Vuex, для Pinia существуют пакеты расширяющие функциональность. На github можно найти ряд интересных плагинов.

Пакет prazdevs/pinia-plugin-persistedstate позволяет хранить состояние в localStorage или sessionStorage, а не просто в ОЗУ.

PiniaORM – плагин для работы с хранилищем Pinia в ORM-стиле. Многие спросят зачем ORM во front-end. Однако, многие приложения имеют дело с данными, которые по своей природе являются вложенными или реляционными. Например, редактор блога может иметь много сообщений, каждое сообщение может иметь множество комментариев, и как сообщения, так и комментарии будут написаны пользователем. Использование данных в такой «вложенной или реляционной» структуре может быть очень трудным для приложений JavaScript, особенно для тех, которые используют глобальное состояние, такое ​​как предоставляет Pinia.

Pinia Debounce – пакет, который использует подход Debouncing (предотвращает слишком частый запуск событий). Вам необходимо указать время, которое приложение будет ждать прежде чем выполнит событие данного типа. Если за этот промежуток произойдет много событий, то выполнится только последнее. Это может быть полезно, например, когда пользователь что-то быстро набирает в поле поиска. Если делать запрос к серверу после каждой буквы, то запросов будет происходить очень много. Если же делать задержку, то можно будет делать запрос к серверу лишь когда пользователь остановил набор на некоторое время.

PiniaUndo – возможность перемещения по истории изменений состояния Pinia через операции Undo/Redo.

Пакетов, на самом деле, больше. Конечно, можно писать свои плагины для Pinia.

Такая функциональность есть также в библиотеке VueUse, о которой рассказывалось в прошлой статье. Стоит проанализировать что удобнее и выгоднее будет использовать – плагин для Pinia или VueUse. Если нужно иметь какую-либо из вышеописанных возможностей для хранилища Pinia (например, хранение данных localStorage), то более естественный и понятный путь – использование плагина.

Полезные ссылки

  1. Документация Pinia. Migrating from Vuex ≤4
  2. VueSchool. How to Migrate from Vuex to Pinia
  3. Pinia vs Vuex – Why Pinia wins

Оставить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *