Problem description
First of all, about the data loss problem in vuEX page refresh, in fact, another way to describe it is: the data initialization problem in VUEX page refresh
Personal opinion: VuEX data is not lost, but initialized, back to the initial value, back to the origin
The use of vuex is not covered in this article, but can be found in the previous article: juejin.cn/post/696550…
Vuex can be understood as a public space, all components can share the state data of the space, you can modify or read) data in this space, but the state of the spatial data is the initial value, for example, information on the page menu data because menu information need to be stored in vuex, Shared data as a global Commons.
- The state repository has a menuArr, which starts with an empty array. This empty array holds the array data of the dynamic menu passed from the back end. You can read the article about dynamic menu: juejin.cn/post/701769…
- The initial page for accessing the project is the login page. After successful login, the user will send a request to obtain the data of the dynamic menu returned by the back end, and then store the data in menuArr in state in VUEX, and jump to the home page of the project at the same time
- At this point, the left menu bar component on the page reads the menuArr data in vuEX and renders it, and the user can operate normally. But!
- When the user refreshes (e.g. on the home page), the route remains on the home page. But:
Both the data in data in the.vue component and the data in State in vuEX are returned to their initial state.
- So the menuArr array in VUex will be empty again, and since vue is reactive, when menuArr is empty, the left menu bar component will not render anything, so it will be gone, so it looks like:
Page refresh data is lost
After analyzing the cause of the problem, the next step is to try to solve it.
Solution 1 Store a copy locally
The login page
In the login.vue component login we trigger the action. The requested interface can be written in the action or component. Here, I need to reuse the action, so I put the request inside the action.
/* login.vue page */
<template>
<div class="loginBox">
<el-button type="primary" @click="loginIn">Click login</el-button>
</div>
</template>
<script>
export default {
name: "CodeLogin".methods: {
loginIn() {
this.$store.dispatch("naviBar/getMenu") // Notify action to send the request
this.$router.push({ path: "/" }) // Jump to the home page,}}};</script>
Copy the code
NaviBar module in VUEX
/* The naviBar module in vuex */
// To make a request, you need a vue instance
import Vue from 'vue'
const that = new Vue()
/* VuEX data refresh lost, solution 1, local save a */
const naviBar = {
state: {
menuArr: JSON.parse(sessionStorage.getItem('menuArr'))?JSON.parse(sessionStorage.getItem('menuArr':)) []},mutations: {
setMenu(state, payload) {
state.menuArr = payload
},
},
actions: {
async getMenu({ commit }, menu) {
let res = await that.$api.getMenuData()
console.log('Menu data', res);
sessionStorage.setItem('menuArr'.JSON.stringify(res.data)) // Store a copy locally
commit("setMenu", res.data) / / submit mutation}},namespaced: true
}
export default naviBar
Copy the code
Where you need to use vuex data, that is, the home page of home.vue, you can directly use calculated attributes to fetch the corresponding VUex data and use it in HTML. computed: { menuArr(){ return this.$store.state.naviBar.menuArr } }
Project analysis
This solution solves the problem, but if the user manually clears the vuex data stored in the SessionStorage of the browser Application, the user will still lose it and the left menu will still disappear.
Passerby a: Will users operate like this, black question mark?
So we decided to use the second option, when the page refreshes, just send the request again (no browser storage).
Solution 1 Refresh the page and resend the request
The login.vue page is left untouched
NaviBar module in VUEX
Page refresh resends the request and vuex does not need to write too complicated.
// To make a request, you need a vue instance
import Vue from 'vue'
const that = new Vue()
/* VuEX data refresh lost, solution 2, send the request again */
const naviBar = {
state: {
menuArr: []},mutations: {
setMenu(state, payload) {
state.menuArr = payload
},
},
actions: {
async getMenu({ commit }, menu) {
let res = await that.$api.getMenuData()
commit("setMenu", res.data)
},
},
namespaced: true
}
export default naviBar
Copy the code
The outer page resends the request
Notice the outer view, which selects the location according to the view structure of the VUE project. I wrote it in home.vue because this page also needs to use menuArr data from VUex, which is also the outer view
export default {
name: "Home".created() {
/* If the menuArr in vuex is not the initial value, send a request to retrieve the menuArr from the menu bar again. The home page component also sends a request when it loads. Reduce the number of times the request is sent */
if (JSON.stringify(this.$store.state.naviBar.menuArr) == "[]") {
this.$store.dispatch("naviBar/getMenu"); }},computed: {
menuArr() {
return this.$store.state.naviBar.menuArr; }},... };Copy the code
Project analysis
This works and reduces the use of local storage, but increases the number of requests and times. Compared with the previous scheme, each has its own advantages and disadvantages.
Other options
You can also use plug-in packages such as Vuex-PersistedState…