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、等等等等
    发散开看看,一个地方真的能学到很多东西。。。

  • 相关阅读:
    高斯消元学习
    HDU 4596 Yet another end of the world(解一阶不定方程)
    Codeforces Round #318 div2
    HDU 4463 Outlets(一条边固定的最小生成树)
    HDU 4458 Shoot the Airplane(计算几何 判断点是否在n边形内)
    HDU 4112 Break the Chocolate(简单的数学推导)
    HDU 4111 Alice and Bob (博弈)
    POJ 2481 Cows(线段树单点更新)
    HDU 4288 Coder(STL水过)
    zoj 2563 Long Dominoes
  • 原文地址:https://www.cnblogs.com/heioray/p/10284268.html
Copyright © 2011-2022 走看看