Управление состоянием: Pinia
Когда состояние нужно многим компонентам сразу, его выносят в общее хранилище. Знакомимся с официальным решением — Pinia.
Pinia — официальная библиотека управления состоянием для Vue. Она хранит данные в store — общем месте, доступном из любого компонента приложения.
Зачем нужен общий store
Пропсы и события хороши для соседних компонентов. Но «корзина», «текущий пользователь» или «тема» нужны во многих местах сразу, на разных ветках дерева. Передавать их пропсами через всё дерево мучительно. Store — единый источник правды: любой компонент читает и меняет его напрямую.
Анатомия store
Store описывают функцией defineStore. В ней три части: state (данные), getters (производные значения, как computed) и actions (методы, меняющие state):
import { defineStore } from 'pinia'
export const useCartStore = defineStore('cart', {
state: () => ({ items: [] }),
getters: {
count: (state) => state.items.length,
total: (state) => state.items.reduce((sum, i) => sum + i.price, 0),
},
actions: {
add(item) { this.items.push(item) },
clear() { this.items = [] },
},
})
Использование в компоненте
Компонент вызывает store-хук и работает с ним напрямую — реактивно:
<template>
<p>Товаров: {{ cart.count }} на {{ cart.total }} ₽</p>
<button @click="cart.add({ name: 'Кофе', price: 200 })">Добавить</button>
</template>
<script setup>
import { useCartStore } from './stores/cart'
const cart = useCartStore()
</script>
Любой другой компонент, вызвавший useCartStore(), увидит те же данные — они общие. Это и отличает store от состояния внутри одного компонента.
Промоделируем store на JS
По сути store — это объект с данными, производными значениями и методами. Соберём упрощённую корзину:
function createCartStore() {
const state = { items: [] };
return {
add(item) { state.items.push(item); },
get count() { return state.items.length; },
get total() { return state.items.reduce((s, i) => s + i.price, 0); },
};
}
const cart = createCartStore();
cart.add({ name: "Кофе", price: 200 });
cart.add({ name: "Чай", price: 150 });
console.log("Товаров:", cart.count);
console.log("Сумма:", cart.total);
Вывод:
Товаров: 2 Сумма: 350
Части store
| Часть | Аналог в компоненте | Назначение |
state | ref | сами данные |
getters | computed | производные значения |
actions | методы | изменение state |
Итог
- Pinia — официальное хранилище общего состояния приложения.
- Store описывают
defineStore:state,getters,actions. - Любой компонент через
useStore()читает и меняет одни и те же данные. stateпохож наref,getters— наcomputed,actions— на методы.