Зачем нужна управление состоянием
▸Проблема prop drilling
Когда данные нужно передать через много уровней компонентов, возникает prop drilling. Это делает код шумным и трудноподдерживаемым.
▸Когда нужен state manager
Vuex: классический подход
▸Установка и настройка
1npm install vuex
▸Создание store
1import { createStore } from 'vuex';23const store = createStore({4 state() {5 return {6 count: 0,7 user: null,8 };9 },10 mutations: {11 increment(state) {12 state.count++;13 },14 setUser(state, user) {15 state.user = user;16 },17 },18 actions: {19 async fetchUser({ commit }) {20 const user = await api.getUser();21 commit('setUser', user);22 },23 },24 getters: {25 doubleCount(state) {26 return state.count * 2;27 },28 },29});
▸Использование в компонентах
1<script>2import { mapState, mapMutations, mapActions } from 'vuex';34export default {5 computed: {6 ...mapState(['count', 'user']),7 },8 methods: {9 ...mapMutations(['increment']),10 ...mapActions(['fetchUser']),11 },12};13</script>
Pinia: современный подход
▸Установка
1npm install pinia
▸Создание store
1import { defineStore } from 'pinia';23export const useCounterStore = defineStore('counter', {4 state: () => ({ count: 0 }),5 getters: {6 doubleCount: (state) => state.count * 2,7 },8 actions: {9 increment() {10 this.count++;11 },12 },13});
▸Использование
1<script setup>2import { useCounterStore } from '@/stores/counter';3import { storeToRefs } from 'pinia';45const counterStore = useCounterStore();6const { count, doubleCount } = storeToRefs(counterStore);7const { increment } = counterStore;8</script>
Composition API с Pinia
1export const useCounterStore = defineStore('counter', () => {2 const count = ref(0);3 const doubleCount = computed(() => count.value * 2);45 function increment() {6 count.value++;7 }89 return { count, doubleCount, increment };10});
Сравнение API
▸Мутации vs Actions
Vuex требует мутации для изменения state. Pinia — нет, state мутируется напрямую в actions.
▸Модули vs Отдельные stores
Vuex использует модули для разделения. Pinia — отдельные stores, каждый со своим state, getters, actions.
▸TypeScript
Pinia имеет отличную поддержку TypeScript из коробки. Vuex требует дополнительных усилий.
DevTools
▸Pinia DevTools
Pinia полностью интегрирована с Vue DevTools. Вы можете inspect state, getters и actions.
▸Vuex DevTools
Vuex также поддерживает DevTools, но с более ограниченным API.
Миграция с Vuex на Pinia
▸Пошаговая миграция
Установите Pinia и удалите Vuex
Создайте отдельные stores для каждого модуля
Замените mapState/mapMutations/mapActions на storeToRefs
Перенесите логику из mutations в actions
Проверьте работоспособность
▸Параллельная работа
Pinia и Vuex могут работать одновременно, что позволяет мигрировать постепенно.
Производительность
▸Bundle size
Pinia: ~1.5 KB. Vuex: ~6 KB. Pinia значительно легче.
▸Ре-рендеры
Pinia использует reactive refs, Vuex — observable. Оба оптимизированы, но Pinia проще в отладке.
Когда выбирать Vuex
Когда выбирать Pinia
Заключение
Pinia — официальный successor Vuex. Она проще, легче и лучше интегрирована с Vue 3. Для новых проектов выбирайте Pinia. Миграция с Vuex — постепенный процесс, который можно делать параллельно.