zoukankan      html  css  js  c++  java
  • Vuex数据页面刷新丢失问题解决方案

    用Vue做项目开发很久了,对于vuex能用、会用,但是因为状态脱离页面和刷新丢失两个原因,一直都有种抵触,特别是一些简单的数据都是通过query或者本地存储就解决了,然而对于一些复杂内容,不可避免的还是要使用Vuex去处理(真香),但是刷新丢失的问题,的确叫人头大。最近闲下来,我们来研究下怎么干掉这个问题~


    不大了解Vuex的同学,可以先去官网溜溜


    由于Vuex的数据是存储在内存中的,相当于memory cache,当页面刷新的时候内存被清空重载新内容,原来的数据就丢了,为了解决这个我们可以借助浏览器的本地存储来解决,此时我们有两个选择

    • localStorage 真·持久存储
    • sessionStorage 会话期存储

    相比之下localStorage太持久了,不主动清除都会一直在,而sessionStorage更符合Vuex会话期状态管理的设计初衷。因此下文中统一使用sessionStorage来做补充,解决问题。

    有了补充对象之后,我们要做的只有两点
    1、每次在mutation中set state的时候,同步的塞到sessionStorage一份
    2、状态初始化的时候,从sessionStorage中读取相应内容并作为默认值(存在的话)

    看起来很简单,于是第一版方案有了,

    export default new Vuex.Store({
        state: {
            userLevel: sessionStorage.getItem('userLevel') || ''
        },
        mutations: {
            SET_USERLEVEL(state, userLevel) {
                sessionStorage.setItem('userLevel', userLevel)
                state.userLevel = userLevel
            }
        },
        modules: {
        }
    })
    

    这个是解决问题了,但是每个mutation都要sessionStorage.setItem一下实在有点麻烦,而且初始化还要都getItem一遍,我很懒不想写。。。于是我们改进了第二版

    const storeMaker = (state) => {
        // 初始化
        Object.keys(state).map((key) => {
            // 判断类型获取本地存储数据
            if (typeof state[key] === 'object') {
                if (sessionStorage.getItem(key) && JSON.parse(sessionStorage.getItem(key))) {
                    state[key] = JSON.parse(sessionStorage.getItem(key))
                }
            } else if (typeof state[key] === 'number') {
                if (sessionStorage.getItem(key) && parseInt(sessionStorage.getItem(key))) {
                    state[key] = parseInt(sessionStorage.getItem(key))
                }
            } else {
                if (sessionStorage.getItem(key)) {
                    state[key] = sessionStorage.getItem(key)
                }
            }
        })
    
        // 重写set处理
        return new Proxy(state, {
            set: function(target, key, value) {
                let temp = value
                if (typeof temp === 'object') {
                    temp = JSON.stringify(temp)
                }
    
                sessionStorage.setItem(key, temp)
                return Reflect.set(target, key, value)
            }
        })
    }
    
    export default new Vuex.Store({
        state: storeMaker({
            userLevel: ''
        }),
        mutations: {
            SET_USERLEVEL(state, userLevel) {
                state.userLevel = userLevel
            }
        },
        modules: {
        }
    })
    

    内容不多,主要定义了一个storeMaker的函数实现了两个功能
    1、对传入的state初始值判断类型,并尝试从sessionStorage中读取数据替换默认值
    2、通过Proxy重置state的set逻辑,添加同步保存到sessionStorage的逻辑

    其实本来可以通过Proxy重置get逻辑处理取值的问题,但是由于vuex本身通过defineProperty函数重置了get逻辑,在这里使用proxy覆盖会有冲突,因此在初始化的时候直接读取sessionStorage。

    同时也存在一些问题:
    1、目前只处理了一级属性,二级以下属性没处理,对于初始化会有偏差。对于这点处理层级也不宜过深,因为过深的结构设计本来就并不合理,两层基本也足够了。基本处理就是对于state的每个key再去遍历一遍,如果是object(非null非数组非空对象)就重新proxy一下
    2、可以尝试打包成npm包,或者写成Vuex的插件形式,方便使用
    3、等等

    ~状态不好,先写到这,大家有兴趣一起来讨论,清清脑子再来补充~

    联想到的一些点:
    1、memory cache和disk cache?内存怎么清理?js垃圾回收机制?
    2、SessionStorage怎么做到会话期缓存?
    3、session机制怎么回事?
    4、http的无状态?状态保持?客户端保持?服务端保持?
    5、等等等等
    发散开看看,一个地方真的能学到很多东西。。。

  • 相关阅读:
    数据处理
    Interleaving String
    Distinct Subsequences
    caffe 输入图像图像加高斯噪声
    caffe resize用interpolation
    软件測试基本方法(七)之验收測试
    CSS入门学习
    bzoj1458 士兵占据
    Swift高阶函数介绍(闭包、Map、Filter、Reduce)
    每天一点儿Java--list
  • 原文地址:https://www.cnblogs.com/heioray/p/10284268.html
Copyright © 2011-2022 走看看