失败狮计划——在localStorage中保存vuex状态

 发布日期:2018-12-13 12:40:00  阅读次数:阅读数:3  来源:
版权声明:转载请注明出处 https://blog.csdn.net/qq_37952101/article/details/84867756

前言

最近碰到了这么一个需求变动:在当前页点击一个按钮打开一个新的页签(本来是在当前页通过路由跳转进入一个新的组件),对于传统jq项目来说这个应该是不费吹灰之力可以实现的,但是对于vue项目来说就要好好斟酌一下了,当时我想到了3种方法来实现:

  1. 首先,最容易理解的就是构建一个简单的多页应用,即新建一个html入口,不过由于之前没有这样做过,对于要踩哪些坑没有什么把握,同时需要后台进行相关的配置,而这个需求需要马上上线,于是我决定先放弃这个待以后研究。
  2. 直接使用window.open打开新的路由再从vuex种读取之前保存的状态,这种方法直接打开新的页签是无法获取到上一个页面保存在vuex中的信息的。(由于这个项目是多人同时开发而且有些思想不太统一,导致我接手的时候发现有好多路由跳转之前都将一些信息存到了vuex中,个人认为在pc端跨路由最好不要使用vuex,否则刷新页面就啥也没了...)
  3. 既然前两种都暂时行不通,我又想到了使用localStorage保存vuex中的信息,因为之前就面临过刷新页面的尴尬,所以使用了sessionStorage来保存当前登录用户的信息,而sessionStorage存在时效性,故而选择了localStorage。(后来发现直接打开新页签,之前页签的sessionstorage还是存在的)

实现过程

1.在打开新页签之前将需要用的vuex状态保存到localStorage中去,由于这部分内容都在一个模块里面,故可以直接将一个Module保存到localStorage,保存Module对象的时候需要转为JSON字符串(JSON.stringify())。

  1. 读取存入的vuex状态,使用localStorage.getItem()读取之后再用JSON.parse()即可拿到存入的对象。
  2. 那么问题来了,如何将取出的state,action,mutation等以最小的代价放入写好的组件中呢?我为了仿造vuex的引入甚至参考了一下他的源码(真是高大上,读起来真切感觉到了境界的差距)。
  • 引入state
    我们一般在组件中引入的时候用到了扩展运算符,这一部分的原理我以前一直不懂,通过做这个需求也研究了一二。
    观摩vuex的源码发现其mapstate函数返回的是一个对象,那么运行以下代码我们可以发现扩展运算符(解构赋值)可以将值'插入'到原对象中
        let fn = ()=> {
            return{
                b: 1,
                c: 2
            }
        }
        let obj = {
            a: 0,
            ...fn()
        }
        console.log(obj);// {a: 0, b: 1, c: 2}

剩下的就是仿照vuex编写自己用的mapstate辅助函数

const PVLISTSTR = localStorage.getItem('pvList');
const PVLIST = JSON.parse(PVLISTSTR);
const MAPSTATE = () => {
    let res = {};
    Object.keys(PVLIST.state).forEach((k, i) => {
        res[k] = function() {
            return PVLIST.state[k];
        };
    });
    return res;
};

之后在组件中常规引入,成功取到了!

  • 引入mutationaction
    就在我准备依葫芦画瓢准备搞定mutation和action的时候却漠然发现,原来localStorage并没有将这两个东西真正存进去,从浏览器中看到的localStorage里面action和mutation都是空对象...,查阅相关资料发现了这么一句话:JSON 不允许包含函数,JSON.stringify() 会删除 JavaScript 对象的函数,包括 key 和 value。不过我们可以先将函数转化为字符串再将整个对象转化为JSON字符串。这样的话就得先遍历一遍mutation和action了,到这里往后又出现了两个新的问题:
    1>怎么在组件中读取mutation,vuex官网上是这样定义的:Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。类似事件但又不是事件,导致我不知道怎么将他放到组件中去。(原谅我实在看不懂源码了)
    2>怎么使用mutation,在mutation中提交载荷来改变state这是vuex的一套逻辑,但是现在毕竟是仿造的(还不是高仿那种),想在短时间内实现和vuex一样的逻辑对我来说有点不现实。

综上所述我还是果断放弃了localStorage...

重回方法二

前文所述的第三种方案失败了之后,我打算尝试一下第二种方法,如果不行就只好用第一种了,第二种方法使用window.open直接打开新的页签虽然无法将上一个路由中保存的vuex状态带入下一个路由中,但是我打开调式工具发现新的页签中仍然可以使用vuex,这也就为第二种方法创造了无限的可能!接下来的事就简单而繁琐了,将前一个路由要保存的state全部作为vue-router的params传入新页签路由,再通过新页签组件中的created将这些参数存入vuex中。(因为新路由中大量使用了上一个路由保存的state,所以我尽量不改变之前的逻辑)这一个过程比较繁琐但也没有什么难点了,只需要不断测试检查是否有遗漏之处。最后介绍一个小技巧:打开新页签可以这样用window.open(${window.location.origin}${window.location.pathname}#/)在#/后面加上自己的路由。

写在后面

仓促实现这个需求的过程中也暴露出了自己的一些问题,最大的问题就是考虑不周全,使用方法三的时候并没有先充分实验调查就开始写代码,结果浪费了一个晚上的时间写出来的代码都作废了,如果开始写之前就了解到了mutation的问题或许会少走些弯路。

题外话

'失败狮'这个词一出现在我的脑海中我第一个反应是皇家海军,结果百度了一下发现——好吧,我还是提督当久了。

转载请注明出处 https://www.jianshu.com/p/e203ee81022b

如果您有好的新闻与建议,欢迎点击文章投稿

    发表评论

    电子邮件地址不会被公开。

  • 内容

  • 网名