在vue项目中用vuex来做全局的状态管理, 发现当刷新网页后,保存在vuex实例store里的数据会丢失。
其实很简单,因为store里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,store里面的数据就会被清空。就相当于你声明的全局变量存储在堆和栈内存当中,页面刷新之后就会全部销毁,需要你进行重新赋值。
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数mutation 是同步执行,不是异步执行。
正常来说我们的数据是通过接口获取而来,属于异步执行。这时候我们就需要用到actions属性是用来处理异步方法的,通过提交mutations实现实现state更新。
那么问题来了,首先浏览器是多线程的,JS是单线程的(浏览器只给js分配了一个线程),所以当我们页面刷新时vue实例都已经重置挂载完成,组件已经渲染完成,vuex中的数据却消失的情况,因为这时候我们请求的异步数据还在浏览器的任务队列,待队列任务执行完成这时候就会更新state数据了,在我们下次在进入或者切换组件的时候数据就出来了。
这里需要大家可以自行去百度一下浏览器处理同步异步机制。
接下来介绍我们今天的主角 async await
在每次刷新页面时触发 actions mutation 来更新 state数据
在app.vue这个入口组件中,这样就可以保证每次刷新页面都可以触发。
具体的代码如下
// 提交方式
<template>
<div id="app">
<section class="el-container">
<main class="el-main defaultnew">
<!--header 部分-->
<web-header></web-header>
<!--header 部分-->
<router-view></router-view>
<!--footer 部分-->
<web-footer :marginTop="footerTop"></web-footer>
<!--footer 部分结束-->
</main>
</section>
</div>
</template>
<script>
import {
mapState } from 'vuex'
export default {
name: 'App',
computed: {
...mapState({
footerTop: state => state.Sea.footerTop
})
},
created() {
const that = this;
async function loading () {
await that.$store.dispatch('getAboutUs')
await that.$store.dispatch('getOrgInfo')
await that.$store.dispatch('getNavColumn')
}
loading()
}
}
</script>
<style lang="scss">
</style>
或者通过VueRouter路由的beforeEach,代码如下
import Vue from 'vue'
import VueRouter from 'vue-router'
import $store from '@/store'
import _ from 'lodash'
import util from "@/utils/util";
import Logindialog from '@/plugins/login/main'
Vue.use(VueRouter)
const routes = [
........
]
const router = new VueRouter({
mode: 'history',
base: process.env.VUE_APP_PAGE_CONTEXT,
scrollBehavior (to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return {
x: 0, y: to.meta.scrollTop || 0 };
}
},
routes
});
const {
back, replace } = router;
router.back = function() {
this.isBack = true;
back.call(router)
};
router.replace = function(...args) {
this.isReplace = true
replace.call(router, ...args)
};
router.beforeEach(async(to, from, next) => {
const {
title, footerTop } = to.meta
const token = util.cookies.get()
document.title = title || process.env.VUE_APP_NAME
footerTop ? $store.commit('updateFooterTop', footerTop) : $store.commit('updateFooterTop', '0px');
if (token && token !== 'undefined') {
if (_.isEmpty($store.state.user.userInfo)) {
await $store.dispatch('getCurrentUser')
console.log('router update vuex')
}
}
if (to.matched.some(r => r.meta.auth)) {
// 这里暂时将cookie里是否存有token作为验证是否登录的条件
// 请根据自身业务需要修改
if (token && token !== 'undefined') {
next()
} else {
// 强制登录,false关闭close唯一关闭入口
Logindialog({
visible: false})
next()
}
} else {
next()
}
// util.cookies.set('TICKET_$apr1$0K3TLn61$x56trftvGlxbqdVxrwz5z1');
});
export default router
import api from '@/api'
import {
errorCreate, parse } from '@/api/tools'
import util from "@/utils/util";
const $api = api
const userModules = {
state: {
partnerId: process.env.VUE_APP_LIMIT_AREA_ID,
token: util.cookies.get(),
searchWord: null,
userInfo: {
},
aboutUs: {
},
orgInfo: {
}
},
getters: {
userInfo: state => state.userInfo
},
mutations: {
updateAboutUs(state, about) {
state.aboutUs = about
},
updateOrgInfo(state, orgInfo) {
state.orgInfo = orgInfo
},
updateUserInfo(state, userInfo) {
state.userInfo = userInfo
},
updateSearchWord(state, searchWord) {
state.searchWord = searchWord
},
resetLogin(state) {
state.userInfo = {
}
util.cookies.remove('yx-ticket')
}
},
actions: {
async getAboutUs(context) {
//获取关于我们资料存储
await $api.website.getOneContent({
partnerId: context.state.partnerId, columnId: 'cef2ed37be84407ca581fe3c7fabbd2a'})
.then( dates => {
context.commit('updateAboutUs', dates)
}).catch( err => {
errorCreate(`获取关于我们: ${
err}`)
})
},
async getOrgInfo(context) {
await $api.website.getCommonPartnerDetail({
partnerId: context.state.partnerId})
.then( dates => {
context.commit('updateOrgInfo', dates)
}).catch( err => {
errorCreate(`获取单位信息: ${
err}`)
})
},
async getCurrentUser(context) {
await $api.system.getCurrentUser()
.then( dates => {
context.commit('updateUserInfo', dates)
}).catch( err => {
errorCreate(`获取用户信息: ${
err}`)
})
}
}
}
export default userModules