Обновляйте свои магазины Pinia

Автор: Дэвид Нвадиогбу

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

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

Настройка проекта

Для начала, если у вас еще не установлена ​​Pinia в вашем приложении Vue, добавьте ее сейчас. В корневом каталоге выполните следующую команду для установки Pinia:

yarn add pinia
# or with npm
npm install pinia

Затем обновите main.js, чтобы использовать Pinia:

📄 main.js

import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
app.mount("#app");

Создайте папку stores в папке src и добавьте файл с именем counter.js со следующим кодом:

📁src/stores/counter.js

import { defineStore } from "pinia";
export const useCounterStore = defineStore("counter", {
  state: () => {
    return { 
      count: 0
     };
  },
  actions: {
    increment(value = 1) {
      this.count += value;
    },
    decrement(value = 1) {
      this.count -= value;
    },
    reset() {
      this.count = 0;
    }
  },
  getters: {
    doubleCount: (state) => {
      return state.count * 2;
    },
    squareCount: (state) => {
      return state.count ** 2;
    },
  },
});

Мы создали состояние под названием count с несколькими действиями и геттерами, которые могут определять поведение нашего состояния.

Давайте отобразим это в нашем приложении, чтобы проверить, работает ли оно.

Обновите файл App.vue, чтобы он выглядел следующим образом:

📁src/App.vue

<script setup>
import { useCounterStore } from "./stores/counter"
const store = useCounterStore(); //initialize the store
</script>
<template>
  <h1>Counter App</h1>
  <p>Count is {{ store.count }}</p>
  <p>Double count is {{ store.doubleCount }}</p>
  <button @click="store.increment(1)">Add</button>
  <button @click="store.decrement(1)">Subtract</button>
  <button @click="store.reset">Reset</button>
</template>
<style scoped>
</style>

Когда мы запускаем приложение, все работает как надо, но когда мы перезагружаем нашу страницу, значение count сбрасывается в исходное состояние: 0.

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

с помощью часов

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

Для этого мы можем использовать метод watch из Vue.

Обновите main.js, включив в него следующий код:

import { createApp, watch } from "vue";
...
watch(
  pinia.state,
  (state) => {
    localStorage.setItem("counter", JSON.stringify(state.counter));
  },
  { deep: true }
  );

и обновите свой counter.js, включив в него следующий код:

state: () => {
    if (localStorage.getItem("counter"))
      return JSON.parse(localStorage.getItem("counter"));
    return {
      count: 0,
    };
  },

Давайте посмотрим, что здесь делает наш код. В первом блоке кода мы используем метод watch для обнаружения изменений в нашем состоянии. Если есть изменение, мы хотим обновить наше локальное хранилище с этим изменением. Во втором блоке кода, после создания нашего хранилища, мы проверяем, есть ли уже значение для нашего состояния счетчика в localStorage. Если есть, мы затем устанавливаем это значение на наше начальное значение для нашего counter.

useLocalStorage из VueUse

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

Для начала установите библиотеку VueUse:

yarn add @vueuse/core
# or with npm
npm i @vueuse/core

Теперь мы можем импортировать useLocalStorage в наш код и получить постоянство всего в одной строке кода.

Обновите хранилище счетчиков, включив в него следующий код:

📁src/stores/counter.js

import { useLocalStorage } from "@vueuse/core"
state: () => {
    return {
     count: useLocalStorage('count', 0), //useLocalStorage takes in a key of 'count' and default value of 0
    };
  },

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

Последний подход, который мы собираемся рассмотреть, — это использование плагина. Отличным примером является плагин Pinia под названием persistedstate. Это крошечный пакет с широкими возможностями настройки, совместимый как с Vue 2, так и с Vue 3, и (на момент написания этой статьи) активно поддерживаемый.

Чтобы использовать это, мы должны установить его:

yarn add pinia-plugin-persistedstate
# or with npm
npm i pinia-plugin-persistedstate

Обновите файл main.js, чтобы использовать плагин:

📁src/main.js

...
import piniaPluginPersistedState from "pinia-plugin-persistedstate"
const pinia = createPinia();
pinia.use(piniaPluginPersistedState)

Наконец, добавьте свойство с именем persist и задайте для него значение true в объекте хранилища счетчиков.

📁src/stores/counter.js

export const useCounterStore = defineStore("counter", {
  state: () => {
    return {
     count: 0,
    };
  },
  ...
  persist: true,
});

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

export const useCounterStore = defineStore("counter", {
  state: () => {
    return {
     count: 0,
    };
  },
  ...
  persist: {
    storage: sessionStorage, // data in sessionStorage is cleared when the page session ends.
  },
});

Все доступные параметры конфигурации объясняются здесь.

Куда пойти отсюда

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

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

Если вам интересно узнать о пинии, вам следует ознакомиться с нашим курсом по основам пинии, который преподает Сандра Роджерс.

Первоначально опубликовано на https://www.vuemastery.com 31 октября 2022 г.