在vue项目中用vuex来做全局的状态管理, 发现当刷新网页后,保存在vuex实例store里的数据会丢失。

1.产生原因

其实很简单,因为store里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,store里面的数据就会被清空。就相当于你声明的全局变量存储在堆和栈内存当中,页面刷新之后就会全部销毁,需要你进行重新赋值。

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数mutation 是同步执行,不是异步执行。
正常来说我们的数据是通过接口获取而来,属于异步执行。这时候我们就需要用到actions属性是用来处理异步方法的,通过提交mutations实现实现state更新。
那么问题来了,首先浏览器是多线程的,JS是单线程的(浏览器只给js分配了一个线程),所以当我们页面刷新时vue实例都已经重置挂载完成,组件已经渲染完成,vuex中的数据却消失的情况,因为这时候我们请求的异步数据还在浏览器的任务队列,待队列任务执行完成这时候就会更新state数据了,在我们下次在进入或者切换组件的时候数据就出来了。
这里需要大家可以自行去百度一下浏览器处理同步异步机制。

2.解决思路

接下来介绍我们今天的主角 async await

3.解决过程

在每次刷新页面时触发 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

在这里插入图片描述

store接收方式
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

在这里插入图片描述
效果如下:
在这里插入图片描述

Logo

前往低代码交流专区

更多推荐