В Vue.js концепция store реализуется через библиотеку
Pinia, которая пришла на смену Vuex начиная с Vue 3.
Store представляет собой централизованное хранилище
состояния приложения, позволяющее управлять данными между компонентами
без необходимости передачи их через пропсы или события.
storeДля создания store используется функция
defineStore. Она принимает два обязательных параметра:
id — уникальное имя
хранилища.Пример структуры:
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
history: []
}),
getters: {
doubleCount: (state) => state.count * 2
},
actions: {
increment() {
this.count++
this.history.push({ action: 'increment', value: this.count })
},
decrement() {
this.count--
this.history.push({ action: 'decrement', value: this.count })
}
}
})
Ключевые моменты:
state — функция, возвращающая объект с начальными
данными.getters — вычисляемые свойства, которые зависят от
состояния.actions — методы для изменения состояния. Они могут
быть синхронными и асинхронными.store в компонентахПосле создания хранилища его можно подключить в любом компоненте с
помощью вызова функции useStore:
<template>
<div>
<p>Счетчик: {{ counter.count }}</p>
<p>Двойной счетчик: {{ counter.doubleCount }}</p>
<button @click="counter.increment">Увеличить</button>
<button @click="counter.decrement">Уменьшить</button>
</div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
</script>
Особенности использования:
state доступно напрямую через свойства
объекта store.actions вызываются через
store.methodName().getters можно использовать как обычные свойства
объекта.storeActions поддерживают асинхронные операции, что позволяет
выполнять запросы к API или работать с таймерами:
actions: {
async fetchData() {
try {
const response = await fetch('https://api.example.com/data')
const data = await response.json()
this.history.push({ action: 'fetch', data })
} catch (error) {
console.error('Ошибка при получении данных:', error)
}
}
}
storeВ больших приложениях рекомендуется разделять состояние на отдельные
store по функциональным модулям. Например:
userStore — управление пользователями и
авторизацией.productStore — данные товаров.cartStore — корзина и покупки.Компоненты могут одновременно подключать несколько store
и использовать их независимо друг от друга:
<script setup>
import { useUserStore } from '@/stores/user'
import { useCartStore } from '@/stores/cart'
const user = useUserStore()
const cart = useCartStore()
</script>
Pinia позволяет реагировать на изменения данных с помощью метода
$subscribe:
const counter = useCounterStore()
counter.$subscribe((mutation, state) => {
console.log('Изменение состояния:', mutation, state)
})
Параметры функции обратного вызова:
mutation — объект с информацией о том, какое действие
вызвало изменение.state — актуальное состояние store после
мутации.Для того чтобы состояние store сохранялось после
перезагрузки страницы, используется плагин
pinia-plugin-persistedstate:
import { defineStore } from 'pinia'
export const useCartStore = defineStore('cart', {
state: () => ({
items: []
}),
actions: {
addItem(item) {
this.items.push(item)
}
},
persist: true
})
После включения persist: true данные будут храниться в
localStorage и автоматически подгружаться при следующем
запуске приложения.
storegetters для вычислений.
Не дублировать вычисляемые значения в state.store по логическим модулям.
Упрощает поддержку и тестирование.Pinia полностью поддерживает TypeScript. Типизация состояния и действий позволяет предотвратить ошибки на этапе компиляции:
interface CounterState {
count: number
history: { action: string, value: number }[]
}
export const useCounterStore = defineStore<'counter', CounterState>({
id: 'counter',
state: (): CounterState => ({
count: 0,
history: []
}),
getters: {
doubleCount: (state) => state.count * 2
},
actions: {
increment() {
this.count++
}
}
})
Store в Vue.js с Pinia обеспечивает мощный и гибкий
инструмент для управления состоянием приложения, позволяя создавать
масштабируемые, модульные и легко поддерживаемые проекты.