Pinia vue что это
Перейти к содержимому

Pinia vue что это

  • автор:

Pinia: Приятное хранилище для Vue

Pinia: Приятное хранилище для Vue

Начиная с зимы 2021 года Pinia является официально рекомендуемым решением для управления состоянием в Vue.js. Используйте его для создания центрального хранилища данных, которое работает как с Options API, так и с Composition API.

Pinia — отличный выбор для управления состоянием, потому что:

  • имеет интуитивный API,
  • обеспечивает типизацию для точного автодополнения,
  • включает поддержку инструментов разработчика Vue.js,
  • имеет плагинную систему, позволяющую легко расширять его функциональность,
  • модульный по дизайну, что обеспечивает более организованный код и автоматическое удаление неиспользуемого кода (treeshaking),
  • является крайне легковесным, размером около 1 КБ.

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

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

Вступление ​

Pinia начиналась как эксперимент по перепроектированию того, как может выглядеть хранилище для Vue с Composition API примерно в ноябре 2019 года. С тех пор начальные принципы остались неизменными, но Pinia работает как для Vue 2, так и для Vue 3 и не требует использования composition API. API одинаков для обоих вариантов, за исключением установки и SSR, и эта документация ориентирована на Vue 3 с примечаниями для Vue 2, когда это необходимо, чтобы ее могли читать пользователи Vue 2 и Vue 3!

Почему вы должны использовать Pinia? ​

Pinia — это библиотека для создания хранилища для Vue, которая позволяет вам совместно использовать состояние между компонентами/страницами. Если вы знакомы с Composition API, вы, возможно, думаете, что уже можете совместно использовать глобальное состояние с помощью простого export const state = reactive(<>) . Это верно для одностраничных приложений (SPA), но при использовании рендеринга на стороне сервера (SSR) это может привести к уязвимостям безопасности. Но даже в небольших одностраничных приложениях вы получаете много возможностей от использования Pinia:

Vue Mastery Logo

  • Поддержка Devtools
    • Хронология для отслеживания действий, мутаций
    • Хранилища отображаются в компонентах, в которых они используются
    • Легкая отладка с возможностью перемещения во времени
  • Горячая замена модулей (HMR)
    • Изменение вашего хранилища без перезагрузки страницы
    • Сохранение существующего состояния в процессе разработки
  • Плагины: расширение возможностей Pinia с помощью плагинов
  • Полноценная поддержка TypeScript или автозаполнение для пользователей JS
  • Поддержка рендеринга на стороне сервера (SSR)

Получить шпаргалку по Pinia от Vue Mastery

Простой пример ​

Вот как выглядит использование Pinia в терминах его API (не забудьте посмотреть руководство по началу работы, чтобы получить полную инструкцию). Начнем с создания хранилища:

// stores/counter.js import from 'pinia' export const useCounterStore = defineStore('counter',  state: () =>  return < count: 0 >  >, // также может быть объявлено как // state: () => (< count: 0 >)  actions:  increment()  this.count++  >,  >, >)
// stores/counter.js import  defineStore > from 'pinia' export const useCounterStore = defineStore('counter',  state: () =>  return  count: 0 > >, // также может быть объявлено как // state: () => (< count: 0 >) actions:  increment()  this.count++ >, >, >)

Затем вы используете его в компоненте:

script setup> import from '@/stores/counter' const counter = useCounterStore() counter.count++ // автозаполнение ✨ counter.$patch(< count: counter.count + 1 >) // или используете действие (action) вместо этого: counter.increment() script> template>  div>Current Count: >div> template>
script setup> import  useCounterStore > from '@/stores/counter' const counter = useCounterStore() counter.count++ // автозаполнение ✨ counter.$patch( count: counter.count + 1 >) // или используете действие (action) вместо этого: counter.increment() script> template>  div>Current Count: >div> template>

Вы даже можете использовать функцию (аналогичную setup() в компоненте) для определения хранилища для более сложных случаев использования:

export const useCounterStore = defineStore('counter', () =>  const count = ref(0) function increment()   count.value++  > return >)
export const useCounterStore = defineStore('counter', () =>  const count = ref(0) function increment()  count.value++ > return  count, increment > >)

Если вы еще не знакомы с setup() и Composition API, не переживайте, Pinia также поддерживает набор map-помощников, аналогичных Vuex. Вы определяете хранилища так же, как и раньше, но затем используете mapStores() , mapState() , или mapActions() :

const useCounterStore = defineStore('counter',  state: () => (< count: 0 >),  getters:  double: (state) => state.count * 2,  >,  actions:  increment()  this.count++  >,  >, >) const useUserStore = defineStore('user',  // .  >) export default defineComponent(  computed:  // другие вычисляемые свойства // .  // предоставляет доступ к this.counterStore и this.userStore . mapStores(useCounterStore, useUserStore), // предоставляет доступ только для чтения к this.count и this.double . mapState(useCounterStore, ['count', 'double']),  >,  methods:  // предоставляет доступ к this.increment() . mapActions(useCounterStore, ['increment']),  >, >)
const useCounterStore = defineStore('counter',  state: () => ( count: 0 >), getters:  double: (state) => state.count * 2, >, actions:  increment()  this.count++ >, >, >) const useUserStore = defineStore('user',  // .  >) export default defineComponent( computed:  // другие вычисляемые свойства // .  // предоставляет доступ к this.counterStore и this.userStore . mapStores(useCounterStore, useUserStore), // предоставляет доступ только для чтения к this.count и this.double . mapState(useCounterStore, ['count', 'double']), >, methods:  // предоставляет доступ к this.increment() . mapActions(useCounterStore, ['increment']), >, >)

Более подробную информацию о каждом из помощников для отображения (map helpers) вы найдете в разделе «Основные концепции».

Почему Pinia

Pinia (произносится /piːnjʌ/ , как «peenya» на английском) — это слово, наиболее близкое к «piña» (ананас на испанском), которое является допустимым именем пакета. На самом деле ананас — это группа отдельных цветов, которые объединяются, создавая несколько плодов. Подобно хранилищам, каждый из них рождается отдельно, но в конечном итоге все они соединяются. Это также вкусный тропический фрукт, происходящий из Южной Америки.

Более реалистичный пример ​

Вот более полный пример использования API, которое вы будете использовать с Pinia с типами даже в JavaScript. Для некоторых людей этого может быть достаточно, чтобы начать, даже без дальнейшего чтения, но мы всё же рекомендуем ознакомиться с остальной документацией или даже пропустить этот пример и вернуться к нему после прочтения всех Основных концепций.

import from 'pinia' export const useTodos = defineStore('todos',  state: () => ( /** @type []> */  todos: [], /** @type  */  filter: 'all', // тип будет автоматически приведен к числу  nextId: 0,  >),  getters:  finishedTodos(state)  // автозаполнение! ✨ return state.todos.filter((todo) => todo.isFinished)  >, unfinishedTodos(state)  return state.todos.filter((todo) => !todo.isFinished)  >, /**  * @returns []>  */ filteredTodos(state)  if (this.filter === 'finished')  // вызов других геттеров (getters) с автозаполнением ✨ return this.finishedTodos  > else if (this.filter === 'unfinished')  return this.unfinishedTodos  > return this.todos  >,  >,  actions:  // любое количество аргументов, возвращает Promise или нет addTodo(text)  // можно изменять состояние напрямую this.todos.push(< text, id: this.nextId++, isFinished: false >)  >,  >, >)
import  defineStore > from 'pinia' export const useTodos = defineStore('todos',  state: () => ( /** @type < text: string, id: number, isFinished: boolean >[]> */ todos: [], /** @type 'all' | 'finished' | 'unfinished'> */ filter: 'all', // тип будет автоматически приведен к числу nextId: 0, >), getters:  finishedTodos(state)  // автозаполнение! ✨ return state.todos.filter((todo) => todo.isFinished) >, unfinishedTodos(state)  return state.todos.filter((todo) => !todo.isFinished) >, /**  * @returns < text: string, id: number, isFinished: boolean >[]>  */ filteredTodos(state)  if (this.filter === 'finished')  // вызов других геттеров (getters) с автозаполнением ✨ return this.finishedTodos > else if (this.filter === 'unfinished')  return this.unfinishedTodos > return this.todos >, >, actions:  // любое количество аргументов, возвращает Promise или нет addTodo(text)  // можно изменять состояние напрямую this.todos.push( text, id: this.nextId++, isFinished: false >) >, >, >)

Сравнение с Vuex ​

Pinia начала свой путь как исследование того, как может выглядеть следующая версия Vuex, включая множество идей, обсуждаемых в команде разработчиков для Vuex 5. В конечном итоге мы поняли, что Pinia уже реализует большую часть того, что мы хотели видеть в Vuex 5, и решили рекомендовать Pinia вместо него.

По сравнению с Vuex, Pinia предоставляет более простой API с меньшим количеством формальностей, предлагает API в стиле Composition API и, что самое важное, обеспечивает надежную поддержку вывода типов при использовании TypeScript.

RFCs ​

Изначально Pinia не проходила через процесс RFC (Request for Comments). Я тестировал идеи, опираясь на свой опыт разработки приложений, изучение код других разработчиков, работу с клиентами, использующими Pinia, и ответы на вопросы в Discord. Это позволило мне предложить решение, которое работает и адаптировано к различным случаям и размерам приложений. Ранее я часто публиковал обновления и развивал библиотеку, сохраняя её основной API неизменным.

Теперь, когда Pinia стала рекомендуемым средством управления состоянием, она подлежит тому же процессу RFC, что и другие основные библиотеки в экосистеме Vue, и её API находится в стабильном состоянии.

Сравнение с Vuex 3.x/4.x ​

Vuex 3.x — это Vuex для Vue 2, а Vuex 4.x — для Vue 3

API Pinia сильно отличается от Vuex ≤4, а именно:

  • мутаций (mutations) больше не существуют. Их часто воспринимали как чрезмерно многословные. Изначально они вносили интеграцию с Devtools, но теперь это больше не является проблемой.
  • Не нужно создавать сложные пользовательские обёртки для поддержки TypeScript; всё типизировано, и API разработано таким образом, чтобы максимально использовать вывод типов в TypeScript.
  • Больше нет магических строк для инъекции; импортируйте функции, вызывайте их и наслаждайтесь автозаполнением!
  • Нет необходимости динамически добавлять хранилища; они все являются динамическими по умолчанию, и вы даже не заметите этого. Обратите внимание, что вы всё равно можете вручную использовать хранилище для его регистрации в любое время, но поскольку это происходит автоматически, вам не нужно об этом беспокоиться.
  • Больше нет вложенного структурирования модулей (modules). Вы по-прежнему можете неявно вкладывать хранилища, импортируя и используя одно хранилище внутри другого, но Pinia предлагает плоскую структуру по дизайну, сохраняя при этом возможности перекрестной композиции между хранилищами. Вы даже можете иметь циклические зависимости между хранилищами.
  • Нет модулей с пространством имён (namespaced modules). Учитывая плоскую архитектуру хранилищ, «пространство имён» хранилищ встроено в то, как они определяются, и можно сказать, что все хранилища имеют свои собственные пространства имён.

Для более подробных инструкций о том, как преобразовать существующий проект с использованием Vuex ≤4 для использования Pinia, смотрите Руководство по миграции с Vuex.

6 простых принципов написания приложения на Vue, которое легко поддерживать (часть 1)

Привет! Меня зовут Наташа Калачева. Я Frontend-разработчик в компании AGIMA. Vue — один из самых популярных фреймворков JS, его используют для разработки SPA и PWA. А его главные плюсы — это понятная, четкая документация, готовая структура и низкий порог входа.

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

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

Следуя этим рекомендациям, вы сможете создавать более эффективные проекты.

1. Делать простую масштабируемую структуру

Базовая структура папок

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

После инициализации приложения с Vue CLI мы уже видим предложенную структуру.

Фотография

Assets: здесь организуем хранение файлов CSS, шрифтов и изображений.

Components: это автономные компоненты Vue, которые одновременно инкапсулируют структуру шаблона, логику JavaScript и представление CSS.

Router: хранит все настройки роутинга и маршруты.

Store: содержит конфиг и данные хранилища ( Vuex, Pinia).

Хорошая практика — придерживаться уже готового решения и расширять по мере необходимости. Хотя Vue не дает строгих рамок и мы можем менять файловую структуру как хотим, всё же использование знакомых стандартов делает проект более предсказуемым и простым.

Расширение базовой структуры

Это хороший старт, но в больших приложениях мы неизбежно расширяем эту структуру. Лучше сделать это в начале разработки, а не пытаться изменить, когда дедлайн близко. О чем же нужно задуматься на берегу?

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

На какие папки можно разделить компоненты?

Components (ui). Здесь хранятся компоненты дизайн-системы. Это самые простые элементы интерфейса, которые часто переиспользуются. Обычно эти компоненты взаимодействуют с «внешним миром» через пропсы и события. Обращение из них к стору и роутингу будет лишним. Чаще всего они не отправляют запросов к серверу и не содержат сложной бизнес-логики.

Примеры таких компонентов: инпуты, кнопки, алерты и другие UI-элементы.

Фотография

Blocks. Это компоненты блоков. Блок — небольшой кусок интерфейса, который состоит из компонентов и уже имеет бизнес-логику. Примером блока может служить карточка продукта. Важно также хранить блоки простыми, не обращаться из них к стору, к роуту, не делать лишних запросов. Чаще всего таким компонентам достаточно информации из пропсов. Это позволит переиспользовать один блок для нескольких страниц.

Views/pages. Страницы собираются из блоков и компонентов, но сами по себе являются более сложными компонентами, из которых мы обращаемся к стору, роутингу и т. д.

Layouts. Хранит компоненты-макеты с данными, которые используются для нескольких страниц. На нем обычно присутствует Footer, Header, глобальный прелоадер и др. Например, может быть один макет для авторизованных пользователей, другой — для страницы авторизации.

Помимо компонентов, важно организовать хранение дополнительного JS-кода.

Plugins. В этой папке храним все сторонние библиотеки, там же их инициализируем и настраиваем.

Hooks. Можно выделить отдельную папку для хранения кода, использующегося в Setup-компонентах (composition API).

Helpers. Помощники будут содержать вспомогательные функции, которые вы хотели бы использовать в своем приложении. Например, функции форматирования, конвертирования данных или валидаторы.

API/services. Папка содержит все функции вызова API.

Constants. Всё, на что в приложении будут ссылаться глобально, но не хранится в .env, можно хранить здесь. Это могут быть статические данные или, например, список типов глобальных окон, которые можно вызвать глобально (через эмиттеры).

Interfaces, enums. Если вы используете Typescript, то сразу можно выделить папку для типов и перечислений.

Эти папки описаны для примера и общего представления о том, как можно разделять кодовую базу. Конечно, можно видоизменять это под потребности проекта. Например, кто-то предпочитает хранить в /pages не только сам компонент страницы, но и папку этой страницы вместе со всеми используемыми блоками. Может быть удобно в папке /views хранить pages, store, blocks для каждого сервиса приложения.

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

2. Выделять все запросы к API

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

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

Фотография

Каждый файл хранит и экспортирует нужные функции по категориям. Например, products.js может содержать следующее:

export function getProduct (id) < return axios.get(`$/products/$`) > export function postProduct (data) < return axios.post(`$/products`, data) > export function patchProduct (data) < return axios.patch(`$/products`, data) > 

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

Далее мы можем использовать расширенный вариант функции в сторе или методах компонента, нанизывая бизнес-логику, хранение данных, отлов ошибок. Например, в сторе:

import < getProduct >from '@/api/products' import < IProduct >from '@/interfaces' const actions = < async fetchProduct (< commit >, id: string): Promise  < try < commit('setIsLoading', true) const response = await getProduct(id) commit('setProduct', response.data) return response.data >catch (err) < // отлавливаем ошибки >finally < commit('setIsLoading', false) >> > 

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

methods: < getProductById (id) < return axios.get(`https://example.com/api/products/$`) > > 

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

Основной путь к серверу лежит в .env, например VUE_APP_API_URL. Так что доступ к этой переменной возможно получить в любом месте приложения, и он может динамически изменяться в зависимости от окружения.

const API_URL = process.env.VUE_APP_API_URL 

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

Это отлично работает для небольших и средних приложений, в которых не хочется усложнять структуру. Хотя для больших систем можно посмотреть в сторону разделения данных ORM. Подробнее об этом в документации для Vuex ORM. Это плагин Vuex, который позволяет разделять состояние приложения с точки зрения объектов данных (продуктов, пользователей и т. д.) и операций CRUD (создания, обновления, удаления).

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

Стор — централизованное хранилище для всех данных приложения с гарантированной предсказуемостью смены состояний.

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

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

Но всегда ли стор необходим?

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

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

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

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

  • Будут ли данные повторно использоваться где-то еще?
  • Могу ли я вместо этого использовать здесь локальное состояние?
  • Способствует ли использование стора улучшению архитектуры приложения?

Фотография

Предположим, вы решили, что использование стора необходимо. Теперь важно понимать, что по умолчанию хранилище Vuex состоит из одного большого объекта, который содержит всё состояние приложения, мутации, действия и геттеры. Это может привести к раздуванию нашего приложения по мере увеличения его размера и сложности. Поэтому важно разделять хранилище на модули. Модули Vuex — это, по сути, небольшие независимые хранилища, которые объединены в более крупное центральное хранилище.

Примеры разделения на модули:

  • index.js — основной файл стора, который импортирует и хранит все модули;
  • auth.js — хранит состояние авторизации, логин, логаут, рефреш токена и т.д.;
  • user.js — хранит данные юзера и методы, связанные с ними;
  • config.js — хранит настройки приложения.
const defaultState = () => < return < exampleData: < prop1: '1', prop2: '2' >> > const getters = < exampleGetter: (state) =>state.exampleData.prop1 > const mutations = < setExampleData (state, data) < state.exampleData = data >> const actions = < async fetchData (< commit >) < try < const response = await getData() commit('setExampleData', response.data) >catch (err) < console.error(err) >>, > export default

В то же время в основном хранилище мы импортируем модули:

import example from '@/store/example' … … export default < state: defaultState, getters, actions, mutations, modules: < example >> 

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

Pinia vs Vuex: Ананасовый экспресс в светлое будущее

Pinia vs Vuex: Является ли Pinia хорошей заменой Vuex?

Pinia vs Vuex: Является ли Pinia хорошей заменой Vuex?

Введение

Pinia, легковесная библиотека управления состояниями для Vue.js, приобрела популярность в последнее время. Она использует новую систему реактивности во Vue 3 для создания интуитивно понятной и полностью типизированной библиотеки управления состояниями.

Успех Pinia можно объяснить её уникальными возможностями (расширяемость, организация модулей хранилищ, группировка изменений состояния, создание нескольких хранилищ и так далее) для управления хранимыми данными.

С другой стороны, Vuex — это популярная библиотека управления состояниями, созданная для фреймворка Vue, и это рекомендуемая библиотека для управления состояниями основной командой Vue. Vuex уделяет большое внимание масштабируемости приложений, эргономике разработчиков и уверенности в себе. Она основана на той же flux-архитектуре, что и Redux.

В этой статье мы проведём сравнение между Pinia и Vuex. Проанализируем настройку и сильные стороны: сообщества и производительность обоих стейт менеджеров. А также рассмотрим новые изменения в Vuex 5 по сравнению с Pinia 2.

Используемые в этой статье фрагменты кода основаны на Vue 3 Composition API

Настройка

Установка Pinia

Начать работу с Pinia очень просто, поскольку для этого требуется только установка и создание хранилища.

Чтобы установить Pinia, вы можете выполнить следующую команду в терминале:

yarn add pinia # or with npm npm install pinia

Эта версия совместима с Vue 3. Если вы ищете версию, совместимую с Vue 2.x, проверьте ветку v1.

Pinia — это обёртка над Composition API Vue 3. Поэтому вам не нужно инициализировать его как плагин, если только вам не нужна поддержка Vue devtools, поддержка SSR и разделение кода webpack:

//app.js import < createPinia >from 'pinia' app.use(createPinia()) 

В вышеприведённом фрагменте мы добавляем Pinia в проект Vue.js, чтобы использовать глобальный объект Pinia в своём коде.

Чтобы создать хранилище, вы вызываете метод defineStore с объектом, содержащим states, actions и getters, необходимые для создания базового хранилища:

// stores/todo.js import < defineStore >from 'pinia' export const useTodoStore = defineStore( < id: 'todo', state: () =>(< count: 0, title: "Cook noodles", done:false >) >)

Установка Vuex

Vuex также прост в настройке, требует установки и создания хранилища.

Чтобы установить Vuex, мы можем запустить следующие команды в своем терминале:

npm install vuex@next --save # or with yarn yarn add vuex@next --save

Чтобы создать хранилище, вы вызываете метод createStore с объектом, содержащим states, actions и getters, необходимые для создания базового хранилища:

//store.js import from 'vuex' const useStore = createStore( < state: < todos: [ < id: 1, title: '. ', done: true >] >, getters: < doneTodos (state) < return state.todos.filter(todo =>todo.done) > > >)

Чтобы получить доступ к глобальному объекту Vuex, необходимо добавить Vuex в корневой файл проекта Vue.js следующим образом:

//index.js import < createApp >from 'vue' import App from './App.vue' import from './store' createApp(App).use(store).mount('#app')

Использование

Vuex и Pinia обращаются к своим хранилищам немного по-разному.

Использование Pinia

Используя Pinia, доступ к хранилищу можно получить следующим образом.

export default defineComponent( < setup() < const todo = useTodoStore() return < // дает доступ только к определенному состоянию state: computed(() =>todo.title), > >, >)

Обратите внимание, что объект state хранилища опущен при доступе к его свойствам.

Использование Vuex

Используя Vuex, доступ к хранилищу можно получить следующим образом:

import < computed >from 'vue' export default < setup () < const store = useStore() return < // доступ к состоянию в вычисляемой функции count: computed(() =>store.state.count), // доступ к геттеру в вычисляемой функции double: computed(() => store.getters.double) > > >

Сообщество и экосистема

На момент написания этой статьи автором у Pinia было небольшое сообщество, что приводит к небольшому количеству вкладов и решений на Stack Overflow.

Благодаря популярности Pinia в начале это года и её прогрессу на данный момент, сообщество быстро растет. И Pinia стала рекомендованной основной командой Vue.js библиотекой управления состоянием, на момент 2022 года (прим. переводчика).

Vuex, будучи тоже рекомендованной командой Vue.js библиотекой управления состояниями, имеет большое сообщество с основным вкладом членов основной команды. Решения ошибок Vuex легко доступны на Stack Overflow. Однако Эван Ю, рекомендует новые проекты писать с использованием Pinia (прим. переводчика).

Кривая обучаемости и документация

Обе библиотеки управления состояниями довольно просты в освоении, поскольку имеют отличную документацию и обучающие ресурсы на YouTube и в сторонних блогах. Их кривая обучаемости легче для разработчиков с предыдущим опытом работы с библиотеками архитектуры Flux, такими как Redux, MobX, Recoil и другими.

Документация обеих библиотек великолепна и написана в манере, удобной как для опытных, так и для начинающих разработчиков.

Звезды на GitHub

На момент написания этой статьи Pinia имеет два основных релиза: v1 и v2, причем v2 имеет более 7,3K звезд на GitHub. Это, безусловно, одна из самых быстрорастущих библиотек управления состояниями в экосистеме Vue.js, учитывая, что она была первоначально выпущена в 2019 году и является относительно новой.

Между тем, с момента создания библиотеки Vuex и до настоящего времени она выпустила пять стабильных релизов. Хотя v5 находится на экспериментальной стадии, v4 Vuex является самым стабильным релизом на данный момент и имеет около 27,6K звезд на GitHub.

Производительность

И Pinia, и Vuex очень быстры, и в некоторых случаях ваше веб-приложение будет работать быстрее при использовании Pinia по сравнению с Vuex. Этот прирост производительности можно объяснить чрезвычайно малым весом Pinia. Pinia весит около 1 КБ.

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

Сравнение Pinia 2 с Vuex 4

  • Мутаций больше не существует. Они очень часто воспринимались как чрезвычайно многословные. Изначально они привносили интеграцию с devtools, но это больше не проблема.
  • Нет необходимости создавать собственные сложные обёртки для поддержки TypeScript, всё типизировано, а API разработан таким образом, чтобы максимально использовать вывод типов TS.

Это дополнительные выводы, которые делает Pinia при сравнении своей библиотеки управления состояниями с Vuex:

  • В Pinia нет поддержки вложенных хранилищ. Вместо этого она позволяет создавать хранилища по мере необходимости. Тем не менее, хранилища могут быть вложенными неявно, импортируя и используя одно хранилище внутри другого.
  • Хранилища получают пространство имен автоматически по мере их определения. Таким образом, нет необходимости в явном пространстве имен модулей.
  • Pinia позволяет создавать несколько хранилищ и автоматически разделять их в коде бандлера.
  • Pinia позволяет использовать геттеры в других геттерах
  • Pinia позволяет группировать изменения на временной шкале devtools с помощью $patch:
 this.$patch((state) => < state.posts.push(post) state.user.postsCount++ >) .catch(error)

По словам создателя Pinia (Эдуардо Сан Мартин Мороте), который также является членом основной команды Vue.js и активно участвует в разработке Vuex, Pinia и Vuex имеют больше сходств, чем различий:

Pinia старается оставаться как можно ближе к философии Vuex. Он был разработан для тестирования предложения для следующей итерации Vuex и оказался успешным, поскольку в настоящее время у нас есть открытый RFC для Vuex 5 с API, очень похожим на тот, который используется в Pinia. Моё личное желание в этом проекте — переработать опыт использования глобального хранилища, сохранив при этом доступную философию Vue. Я сохраняю API Pinia настолько близким к Vuex, насколько он продолжает двигаться вперёд, чтобы облегчить людям переход на Vuex или даже слияние обоих проектов (под Vuex) в будущем.

Хотя Pinia достаточно хороша, чтобы заменить Vuex, замена Vuex не является её целью, поэтому Vuex остаётся рекомендуемой библиотекой управления состояниями для приложений Vue.js. (Прим переводчика: на момент весны 2022 Pinia — является официальным стейт менеджером, как и Vuex)

Плюсы и минусы Vuex

Плюсы

  • Поддерживает такие функции отладки, как перемещение во времени и редактирование
  • Подходит для крупномасштабных и высокосложных проектов Vue.js

Минусы

  • Начиная с Vue 3, результат геттера не кэшируется, как это делает вычисляемое свойство
  • Vuex 4 имеет некоторые проблемы, связанные с безопасностью типов

Плюсы и минусы Pinia

Плюсы

Полная поддержка TypeScript: добавление TypeScript очень просто по сравнению с добавлением TypeScript в Vuex

  • Исключительно лёгкий (весит около 1 КБ)
  • Действия хранилища отправляются как вызовы обычных функций, а не с помощью метода dispatch или вспомогательной функции MapAction, что часто встречается в Vuex
  • Имеет поддержку нескольких store
  • Поддерживает Vue devtools, SSR и разделение кода webpack.

Минусы

  • Нет поддержки функций отладки, таких как перемещение по времени и редактирование.

Когда использовать Pinia, а когда нужен Vuex

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

Использование Vuex для малых и средних проектов Vue.js является излишеством, поскольку его вес сильно влияет на снижение производительности. Следовательно, Vuex подходит для крупномасштабных и высокосложных проектов Vue.js.

Заключение

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

Vuex 4 и Pinia в большинстве своем похожи, и их можно использовать для решения одних и тех же задач.

В целом, один не лучше другого — они оба достигают желаемой цели. Все зависит от вашего сценария использования и предпочтений. Также следует помнить, что создатель Pinia заявил, что целью Pinia не является замена Vuex. Скорее, её цель — облегчить разработчикам переход на Vuex или даже объединить оба проекта (под Vuex) в будущем.

P.S.: на момент написания и перевода Pinia уже в экосистеме Vue 3.

Добавить комментарий

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