16

我现在有一个 headerBar 组件,上面显示了用户名称(如果设置了昵称显示昵称,否则显示用户名称),当用户点击登录按钮时,调用api获取用户信息,保存到Vuexstate里面,headerBar通过this.$store.getters.xxx来获取用户登录信息,但是当用户刷新时,state里面的用户信息全没了,所以我考虑加入 localStorage 来保存用户信息,但是这部分代码不知道该如何“分布”,因为要考虑用户登录超时,请小伙伴们指点指点,谢谢!

代码如下:

export default new Vuex.Store({
    state: {
        loginInfo: null,//当前用户简要信息
    },
    getters: {
        GET_LOGININFO(state) {
            //先从state里面获取用户登录信息
            let loginInfo = state.loginInfo;
            //如果 state 里面获取不到,那么从localStorage里面获取
            if(!loginInfo){
                loginInfo = JSON.parse(window.localStorage.getItem('loginInfo') || null)
            }
            return loginInfo;
        },
    },
    mutations: {
        SET_LOGININFO(state, data){
            state.userInfo = data.data;
        }
    },
    actions: {
        Login(context, data) {
            axios.post('/api/login', {
                userName: 'admin',
                pwd: '123456'
            })
            .then((res) => {
                //登录成功,保存当前用户信息到 state 里面,以便其他组建获取
                context.commit('SET_LOGININFO', res.data);
                //保存到localStorage里面
                window.localStorage.setItem('loginInfo', JSON.stringify(items));
                return res;                
            })
            .catch(function (error) {});
        },
    }
})

想请教几个问题:
1、这么使用 localStorage 正确么?或者合理么?有没有更好的方法呢?
2、在getters下面的GET_LOGININFO方法里面,如果进入了if(!loginInfo)语句,该方法是否可以为 state 属性loginInfo赋值呢(或者调用mutations方法来给loginInfo赋值)?
3、这样的话,如果用户点击退出按钮,是不是意味着需要清空state的loginInfo,还需要清除localStorage下面的loginInfo呢?
4、这样的话,从客户端角度来看,是不是客户就永远保持以登录状态了?这个环节该怎么做好呢?

补充:第二个问题其实就是:getters里面的方法是否可以为state属性赋值(直接访问state属性赋值 或者 调用mutations方法赋值)?

2017-11-19 提问

查看全部 2 个回答

31

已采纳
  1. 不合理。用户登录成功以后应该在本地保存一份用户数据,注意我说的是保存到本地不是保存到localstorage,因为保存本地的方法有很多种,比如cookieindexedDB等,所以,代码中不应该直接调用window.localStorage,而是应该封装一个用户数据的读取类,解除代码耦合,将来要改成其他存储方式比较简单:

    const USER_INFO='USER_INFO'
    function getUserinfo(){}
    function setUserinfo(){}
  2. 不应该。个人认为不应该,getters语义上就是获取数据,但是却改变了数据,导致不纯净,可能会埋下维护上的隐患。

  3. 是的。理论上应该有一个接口用来更新用户状态,比如判断用户是否需要重新登录之类的,比如api/refresh, 所以逻辑应该是:

    • 用户进入app,判断本地是否有用户信息。

      • 有,调用api/refresh,判断是否需要重新登录。

        • 不需要(连续登录),将信息保存在vuex中,并进入首页,往后数据读取全部走vuex

        • 需要(长时间未登录),删除本地用户信息并跳转到登录流程。

      • 没有, 跳转到登录流程(以下是登录流程)。

        • 调用api/login登录。

        • 将保存到本地,并保存到vuex中,往后数据读取全部走vuex

  4. 看3,具体还可以看看jwt,或者基于tokenapi设计相关的文章。

2

啊哈哈,可能是我写的不够好,我再写一点吧

  1. 可以存到localStorage里面,只是不能直接用window.localStorage相关函数,这边用到的是面相接口编程的思想,在前端没有用上typescript是很难实现的,但是也可以借鉴一些。这么说吧,我假设一个情景,在前期我们要求吧用户信息存储在localStorage中,但是后期,我们又不想存在这里的,我们希望存在cookie甚至其他服务器,那么照你的这种写法,需要替换项目中的所有localStorage调用,所以这里提取出一层,即model层,或者说是存储层,那么我们不需要切换修改所有项目中的localStorage调用,只需要修改model层中的localStorage调用为cookie或者网络连接。这样保持我们调用方式不变:getUserinfo,同时还减小工作量,降低误差。在团队的分工合作中,负责这一层的团队成员直接从localStorage切换成cookie也不会对上层的团队成员造成影响。也就是随意我切换存储引擎不和任何人打招呼我自己也能完成,还不影响他们。而且独立出来以后我可以针对这一部分直接做单元测试,对项目的维护也有很大帮助。关键词:MVC面相接口编程

  2. 最简单的做法就是本地没数据就登录,有数据就刷新,后台判断数据过期了就清除数据再登录。

  3. state里面是为了快一点,我对其他存储环境研究的不太深,可能有的纯粹是本地文件存储而已,总之跟在内存中的state相比,怕是其他方式都是慢的。

followWinter · 2017-11-19

展开评论

推广链接