Сохранение данных Vuex
Когда мы настроили хранилище Vuex, мы можем управлять им или изменять его по мере необходимости. Удивительно, но при обновлении страницы все данные исчезнут. Один из способов решения этой проблемы, сохранить данные в базе данных проекта. Другой способ, который обеспечит работу приложения в автономном режиме, хранить их локально с помощью localStorage.
Рассмотрим, как сохранить данные Vuex в localStorage, чтобы они сохранились после обновления. Вы также можете сохранить их в базе данных и это будет правильным решением.
Первое, что нам нужно сделать, это использовать subscribe метод в нашем хранилище. В main.js нужно добавить код в конец файла. subscribe это событие которое срабатывает каждый раз, когда в нашем хранилище происходит мутация:
src/main.jsstore.subscribe((mutation, state) => {
// код, заключенный в фигурные скобки, срабатывает каждый раз, когда происходит мутация. Каждый раз когда происходит мутация, мы обновляем весь наш объект state
localStorage.setItem('store', JSON.stringify(state));
})
Работа с данными из localStorage
Сохранить данные в localStorage это одно, а отобразить данные в приложении совсем другое. Для этого нам нужно создать новую мутацию, которая заменит все данные в state нашими данными из localStorage, если оно существует:
src/main.jsloadStore() {
if(localStorage.getItem('store')) {
try {
this.replaceState(JSON.parse(localStorage.getItem('store')));
}
catch(e) {
console.log('Не удалось инициализировать хранилище!', e);
}
}
}
Все что делает эта функция, проверяет существует ли в localStorage элемент store, если существует, мы используем функцию replaceState(), которая заменяет в хранилище данные, данными из localStorage.
Нам нужно, чтобы это выполнялось при каждой загрузке приложения, для этого нам нужно добавить код в хук beforeCreate(). beforeCreate() это жизненный хук в API Vue. Он вызывается первым после создания экземпляра компонента, но до инициализации реактивных данных, событий и вычисляемых свойств:
App.vue beforeCreate() {
this.$store.commit('loadStore');
}
Полный код
src/main.jsimport { createApp } from 'vue'
import { createStore } from 'vuex'
import App from './App.vue'
const app = createApp(App);
const store = createStore({
state () {
return {
users: [
{ id: '1', name: 'Иван Иванов', email: 'test@yandex.ru' }
]
}
},
getters: {
users (state) {
return state.users;
}
},
mutations: {
loadStore() {
if(localStorage.getItem('store')) {
try {
this.replaceState(JSON.parse(localStorage.getItem('store')));
}
catch(e) {
console.log('Не удалось инициализировать хранилище!', e);
}
}
},
addUser(state, newUser) {
if (newUser.id !== undefined && typeof newUser.name == 'string' && typeof newUser.email == 'string') {
state.users.push({
id: newUser.id,
name: newUser.name,
email: newUser.email
})
}
}
},
actions: {
}
});
// когда происходит мутация
store.subscribe((mutation, state) => {
// код, заключенный в фигурные скобки, срабатывает каждый раз, когда происходит мутация. Каждый раз когда происходит мутация, мы обновляем весь наш объект state
localStorage.setItem('store', JSON.stringify(state));
})
app.use(store).mount('#app')
App.vue<script>
export default {
data() {
return {
// получаем длину массива
id: this.$store.state.users.length,
}
},
methods: {
newUser: function () {
// используем "commit" для вызова мутаций в Vuex
this.$store.commit('addUser', {
// увеличиваем id на единицу
id: this.id++,
// обращаемся к элементам через ref
name: this.$refs.username.value,
email: this.$refs.email.value
})
let allUsers = JSON.stringify(this.$store.getters.users);
console.log('Добавлен новый пользователь!')
console.log(`Все пользователи: ${allUsers}`);
console.log('Данные добавлены в localStorage!')
console.log(`Все пользователи: ${localStorage.getItem("store")}`)
}
},
beforeCreate() {
this.$store.commit('loadStore');
}
};
</script>
<template>
<div id="new-user">
<input type="text" placeholder="Добавьте имя пользователя" id="username" ref="username">
<input type="text" placeholder="Добавьте email" id="email" ref="email">
<input type="submit" id="submit-user" @click="newUser" value="Submit">
</div>
<p>{{ this.$store.state }}</p>
</template>