两种方式解决页面刷新vuex中数据丢失问题(详细讲解)

简介: 两种方式解决页面刷新vuex中数据丢失问题(详细讲解)

问题描述

首先,关于 页面刷新vuex中数据丢失问题,其实换种方式去描述就是:页面刷新vuex中的数据又初始化问题

个人愚见:vuex的数据并不是弄丢了,而是初始化了,回到初始值,回到原点了

关于vuex的用法本篇文章不赘述,详情可以看之前的文章: https://juejin.cn/post/6965504417764376612

vuex可以理解为是一个公共的空间,所有的组件都可以共享这个空间的状态数据,大家都可以(修改or读取)这个空间的数据,但是,这个空间的数据状态是有初始值的,举例页面上的菜单数据信息,因为菜单信息需要存储在vuex中,作为全局的共用共享的数据。

  • state仓库中有一个menuArr,初始值为一个空数组,这个空数组存放的就是后端传递过来的动态菜单的数组数据,关于动态菜单可以看上一篇文章:https://juejin.cn/post/7017695269550555167
  • 访问项目初始页面为登录页,用户登录成功以后,会发请求获取后端返回的动态菜单的数据,然后把这个数据存放在vuex中的state中的menuArr里面,同时进行页面跳转到项目首页
  • 这时,页面上的左侧菜单栏组件读取vuex中的menuArr数据并渲染出来,用户就可以正常操作了。但是!
  • 当用户一刷新的时候(比如在首页刷新),路由不会变,还是在首页。但是:无论是 .vue组件中的data中的数据,还是vuex中的state中的数据,都会回归到初始状态。
  • 所以vuex中的menuArr数组又会变成空数组,又因为vue是响应式的,当menuArr为空数组的时候,左侧菜单栏组件就渲染不出来东西,所以就没了,所以看着就像:页面刷新数据丢失

分析清楚了问题产生的原因,接下来就是想办法去解决。

解决方案一 本地存储一份

login页面

在login.vue组件中的登录中我们去触发action,请求的接口可以写在action里面,也可以写在组件里面。这里因为需要复用action,所以请求我就写在action里面了。

/* login.vue页面 */
<template>
  <div class="loginBox">
    <el-button type="primary" @click="loginIn">点击登录</el-button>
  </div>
</template>

<script>
export default {
  name: "CodeLogin",
  methods: {
    loginIn() {
      this.$store.dispatch("naviBar/getMenu") // 通知action去发请求
      this.$router.push({ path: "/" }) // 跳转到首页
    },
  },
};
</script>

vuex中的naviBar模块

/* vuex中的naviBar模块 */

// 为了发请求,需要有一个vue实例
import Vue from 'vue'
const that = new Vue()

/* vuex数据刷新丢失,解决方案一,本地存一份*/
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('菜单数据', res);
            sessionStorage.setItem('menuArr', JSON.stringify(res.data)) // 本地存储一份
            commit("setMenu", res.data) // 提交mutation
        },
    },
    namespaced: true
}
export default naviBar

在需要使用vuex中的数据的地方,也就是home.vue首页的地方,直接使用计算属性取到相应vuex数据,在html中使用即可。computed: { menuArr(){ return this.$store.state.naviBar.menuArr } }

方案分析

此方案解决了问题,但是如果用户手动把浏览器的Application中的sessionstorage中存储vuex的数据清空,用户一刷新还是会丢失,左侧的菜单还是会没了。

路人甲:用户会这样操作吗,黑人问号?

所以我们就考虑使用第二种方式,当页面刷新的时候,再重新发一次请求即可(不使用浏览器存储了)

解决方案一 页面刷新重发请求

login.vue页面不用动

vuex中的naviBar模块

页面刷新重发请求,vuex就不需要写太复杂了。

// 为了发请求,需要有一个vue实例
import Vue from 'vue'
const that = new Vue()

/* vuex数据刷新丢失,解决方案二,再重新发请求 */
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

外层页面重发请求

注意是外层视图,这个根据vue项目的视图结构去选择位置。我在home.vue中书写,因为这个页面也需要使用到vuex中的menuArr数据,也是外层视图

export default {
  name: "Home",
  created() {
    /* 
      注意由于数组是引用数据类型,所以 [] 不等于 [] ,这里转换成字符串进行比较
      若vuex中的menuArr不是初始值,就再次发请求重新获取菜单栏的数据
      加一个判断算是优化吧,不加的话,用户登录的时候会发一次,首页组件加载的时候也会发一次请求。
      即减少请求的发送次数
     */
    if (JSON.stringify(this.$store.state.naviBar.menuArr) == "[]") {
      this.$store.dispatch("naviBar/getMenu");
    }
  },
  computed: {
    menuArr() {
      return this.$store.state.naviBar.menuArr;
    },
  },
  ...
};

方案分析

这中方案实现了效果,也减少了本地存储的使用,不过增加了请求和次数。和上一种方案比较,各有优缺点,具体用那种看业务。

其他方案

还可以使用插件包去解决,比如 vuex-persistedstate 等...

相关文章
|
UED
element el-cascader动态加载数据 (多级联动,落地方案)
最近需要用到element ui的这个插件做地区的四级联动,但是碰了一些问题: 官网的说明太泛泛然,不易看懂 网上的教程乱七八糟,代码一堆一堆的 看这篇就对了!!!
2939 0
element el-cascader动态加载数据 (多级联动,落地方案)
|
小程序 API 索引
uniapp中uview组件库中丰富的Picker 选择器用法
uniapp中uview组件库中丰富的Picker 选择器用法
3127 0
element el-cascader动态编辑赋值后,不回显的解决方法(整理)
element el-cascader动态编辑赋值后,不回显的解决方法(整理)
|
移动开发 JavaScript API
Uniapp 与原生 App 集成时如何解决兼容性问题?
Uniapp 与原生 App 集成时如何解决兼容性问题?
1434 136
|
8月前
|
SQL 前端开发 Java
【分层架构】Spring MVC三层架构 / DDD领域驱动四层架构 / 微服务分布式架构(DAO/Mapper/Repository/Service/Controller/Manager)
本文系统解析Java企业级分层架构(Controller/Service/Manager/Repository/DAO/Mapper),阐明各层职责边界、设计原则与典型误区,强调单一职责、依赖倒置、关注点分离等核心思想,助力构建高内聚、低耦合、易维护的可扩展系统。
2060 11
Threejs中导入GLTF模型克隆后合并
这篇文章详细说明了在Three.js中如何导入GLTF模型,对其进行克隆,并将多个克隆模型合并成一个整体模型的过程。
993 2
Threejs中导入GLTF模型克隆后合并
|
前端开发 JavaScript Android开发
移动端点击事件:原理、问题与解决方案
前端技术在移动端点击事件上的应用,涉及触屏交互、响应速度优化及用户体验提升,确保网页或应用在手机等移动设备上流畅运行。
|
搜索推荐 API UED
路由的query参数和params参数
理解并正确使用Query参数和Params参数,是构建清晰、高效Web应用的关键之一。开发者应根据实际应用场景灵活选择参数类型,从而优化用户体验和应用性能。
1553 6
|
JavaScript 前端开发 中间件
异步编程中使用 async/await 是否必须包含 try 和 catch 语句以实现错误处理?
异步编程中使用 async/await 是否必须包含 try 和 catch 语句以实现错误处理?
|
资源调度 JavaScript 前端开发
Prettier 入门:让代码整洁如一
【10月更文挑战第18天】在软件开发过程中,代码的可读性对于团队协作和个人工作效率都至关重要。良好的代码格式不仅能提高代码的可读性,还能减少因风格差异引起的代码审查时间。Prettier 是一款自动代码格式化工具,能够帮助开发者快速统一代码风格,使得团队成员编写的代码具有一致性。本文将介绍 Prettier 的基本用法、安装方式以及如何在常见编辑器中设置和使用 Prettier。
2078 4