Ну что ж, пришло время поговорить о глобальном управлении состоянием в Vue-приложениях. Если вы работали с Vue 2, то наверняка помните о Vuex — официальной библиотеке для управления состоянием. Однако с Vue 3 появился новый инструмент — Pinia, который пришёл на смену Vuex и стал более лёгким, удобным и мощным.

С Pinia вы можете легко управлять состоянием вашего приложения, делая его организованным и масштабируемым. Сегодня мы разберёмся, как настроить и использовать Pinia для управления состоянием, и почему это гораздо проще, чем кажется.

Что такое Pinia?

Pinia — это официальный хранилище для Vue 3, заменяющее Vuex. Оно проще в использовании, не теряя при этом функциональности. Pinia обеспечивает реактивность состояния, модульность и позволяет легко работать с TypeScript.

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

Установка Pinia

Как всегда, начнём с установки. Если вы используете Vite, процесс установки довольно прост:

npm install pinia

Теперь нужно подключить Pinia к вашему приложению. Откройте файл main.js и добавьте Pinia в цепочку использования вашего приложения:

import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';

const app = createApp(App);

// Создаем экземпляр Pinia
const pinia = createPinia();

// Подключаем его к приложению
app.use(pinia);
app.mount('#app');

Вот и всё! Pinia готова к использованию в вашем приложении.

Создание первого хранилища

Теперь давайте создадим хранилище, или, как его называют в Pinia, store. Хранилище — это некий глобальный объект, который может содержать состояние, геттеры (аналог computed), действия и мутации (для изменения состояния).

Создадим файл store/counter.js, который будет представлять наше первое хранилище:

import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
  // Начальное состояние
  state: () => ({
    count: 0
  }),

  // Геттеры — аналог computed
  getters: {
    doubleCount: (state) => state.count * 2
  },

  // Действия — аналог методов
  actions: {
    increment() {
      this.count++;
    },
    decrement() {
      this.count--;
    }
  }
});

Здесь мы создаём хранилище counter с помощью функции defineStore. Внутри определяем:

  • State — начальное состояние. В нашем случае это просто счётчик count, который равен 0.
  • Getters — это свойства, которые вычисляются на основе состояния. Например, doubleCount возвращает удвоенное значение счётчика.
  • Actions — методы, которые могут изменять состояние. Например, метод increment увеличивает счётчик, а decrement — уменьшает.

Использование хранилища в компонентах

Теперь давайте посмотрим, как использовать хранилище в компонентах. Откроем какой-нибудь компонент, например App.vue, и подключим наше хранилище counter.

<template>
  <div>
    <h1>Счётчик: {{ counter.count }}</h1>
    <h2>Удвоенное значение: {{ counter.doubleCount }}</h2>
    <button @click="counter.increment">Увеличить</button>
    <button @click="counter.decrement">Уменьшить</button>
  </div>
</template>

<script>
import { useCounterStore } from './store/counter';

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

    return { counter };
  }
};
</script>

Здесь всё просто: мы импортируем наше хранилище useCounterStore и подключаем его внутри функции setup. Теперь мы можем напрямую обращаться к состоянию (counter.count), геттерам (counter.doubleCount) и методам (counter.increment, counter.decrement).

Pinia автоматически делает все свойства реактивными, так что любое изменение состояния будет сразу отражаться в интерфейсе.

Модульность в Pinia

Что здорово в Pinia — это модульность. Если в вашем приложении есть несколько независимых частей, например, управление пользователями и товары в магазине, вы можете легко разделить их по разным хранилищам.

Например, создадим ещё одно хранилище для управления пользователями:

import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
  state: () => ({
    user: null
  }),

  actions: {
    login(userData) {
      this.user = userData;
    },
    logout() {
      this.user = null;
    }
  }
});

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

Асинхронные действия

Pinia прекрасно поддерживает асинхронные действия. Допустим, вы хотите логиниться через API. Это можно сделать с использованием async внутри вашего хранилища.

Пример асинхронного действия для входа:

actions: {
  async login(username, password) {
    try {
      const user = await api.login(username, password);
      this.user = user;
    } catch (error) {
      console.error('Ошибка при входе:', error);
    }
  }
}

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

Работа с Pinia и TypeScript

Если вы работаете с TypeScript, то Pinia — просто находка! Она полностью совместима с TS и позволяет вам создавать типизированные хранилища, что значительно упрощает работу в больших проектах.

Пример типизированного хранилища:

import { defineStore } from 'pinia';

interface State {
  count: number;
}

export const useCounterStore = defineStore<'counter', State>({
  state: () => ({
    count: 0
  }),
  
  actions: {
    increment() {
      this.count++;
    }
  }
});

Благодаря этому вы получаете все преимущества автодополнения и проверки типов, что минимизирует ошибки и упрощает разработку.

Почему Pinia лучше Vuex?

Pinia пришла на смену Vuex, и на это есть ряд причин:

  • Простота: Меньше бойлерплейта, чем в Vuex. Не нужно вручную создавать мутации.
  • Совместимость с Composition API: Pinia легко интегрируется с Vue 3 и его новыми возможностями.
  • TypeScript: Отличная поддержка типов из коробки.
  • Модульность: Простое разделение состояния на отдельные модули.
  • Асинхронность: Легкость работы с асинхронными действиями.

В целом, Pinia — это новый стандарт для управления состоянием в Vue-приложениях, и его стоит использовать, если вы работаете с Vue 3.

 

Дальше мы закрепим полученные знания из курса. Будет разрабатывать Todolist!

 

Один комментарий