此篇文章是介绍利用 vuex 储存用户登录时的相关信息的使用方法。

声明:前面部分是刚开始对vuex的接触,后面部分是学习后对vuex使用的部分优化,想直接用最新的,可以直接找到 20200819 部分。

效果图:

image.png

使用方法:

相关配置文件

 

image.png

index.js

 

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
Vue.use(Vuex)
export default new Vuex.Store({
    //模块引入
    modules:{
        user:user
    }
})

user.js

 


export const USER_SIGNIN = 'USER_SIGNIN' //登录成功
export const USER_SIGNOUT = 'USER_SIGNOUT' //退出登录
export const USER_INFO_COMMIT = 'USER_INFO_COMMIT' //配合sessionStorage解决vux刷新丢失问题
export default {
    // 存储状态(变量)
    state: {
        userInfo: {},//储存用户相关信息
        userLogin: false,//用户登录状态
    },
    // 对数据获取之前的再次编译,可以理解为state的计算属性 this.$store.getters.方法名。
    getters: {
      
    },
    // 修改状态,并且是同步的。在组件中使用$store.commit('',params)
    mutations: {
        //用户登陆方法
        [USER_SIGNIN](state, user) {
            //储存用户相关信息
            sessionStorage.setItem('userInfo', JSON.stringify(user))
            sessionStorage.setItem('userLogin', 'true')
            if (JSON.stringify(user)) {
                //解决用户信息未及时更新问题
                Object.assign(state.userInfo, sessionStorage.getItem('userInfo') ? JSON.parse(sessionStorage.getItem('userInfo')) : user)
                //更新用户登录状态
                state.userLogin = sessionStorage.getItem('userLogin') ? JSON.parse(sessionStorage.getItem('userLogin')) : false
            }
        },
        //用户退出登录方法
        [USER_SIGNOUT](state) {
            state.userLogin = false;
            state.userInfo = {};
            //清除sessionStorage内的所有记录
            sessionStorage.clear();
        },
        //解决浏览器刷新页面数据丢失问题(根据之前储存的sessionStorage相关信息来判断)
        [USER_INFO_COMMIT](state) {
            Object.assign(state.userInfo, sessionStorage.getItem('userInfo') ? JSON.parse(sessionStorage.getItem('userInfo')) : {})
            state.userLogin = sessionStorage.getItem('userLogin') ? JSON.parse(sessionStorage.getItem('userLogin')) : false;
        },
    },
    // 异步操作
    actions: {
        [USER_SIGNIN]({ commit }, user) {
            commit(USER_SIGNIN, user)
        },
        [USER_SIGNOUT]({ commit }) {
            commit(USER_SIGNOUT)
        },
        [USER_INFO_COMMIT]({ commit }) {
            commit(USER_INFO_COMMIT)
        }
    }
}

main.js

 

import store from './store/index' //引入

/* eslint-disable no-new */
new Vue({
  el: '#app',
  store, //引入
  router,
  components: { App },
  template: '<App/>'
})

配置完成后,就可以直接在vue组件中使用

xxx.vue组件

 

<template>
  <div style="margin:200px 0">
    <p>登录状态:{{userLogin}}</p>
    <p>用户信息:{{userInfo}}</p>
    <button @click="loginIn()">登录</button>
    <button @click="loginOut()">退出</button>
  </div>
</template>

<script>
export default {
  computed: {
    userLogin() {
      if (this.$store.state.user.userLogin) {
         return this.$store.state.user.userLogin;
      } else {
        this.$store.commit("USER_INFO_COMMIT");
        return this.$store.state.user.userLogin;
      }
    },
    userInfo() {
      if (this.$store.state.user.userLogin) {
        return this.$store.state.user.userInfo;
      } else {
        this.$store.commit("USER_INFO_COMMIT");
        return this.$store.state.user.userInfo;
      }
    }
  },
  data() {
    return {
      userMsg: {
        name: "小明",
        age: "18",
        sex: "男"
      }
    };
  },
  methods: {
    loginIn() {
      this.$store.commit("USER_SIGNIN", this.userMsg);
    },
    loginOut() {
      this.$store.commit("USER_SIGNOUT");
    }
  }
};
</script>

<style>
</style>

🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊

20200819代码优化调整:

程序员都是在不断成长的,下面的代码是针对之前使用vuex的部分优化。

 

image.png

模块引入
相比之前的模块引入,这边也是同样按照 modules 目录下,进行的配置。不过是直接通过遍历文件目录实现的,不需要再一个个去写了。

index.js

 

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'

Vue.use(Vuex)
// 把modules文件下的 js文件返回出来
// https://webpack.js.org/guides/dependency-management/#requirecontext
const modulesFiles = require.context('./modules', true, /\.js$/)

// you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  // set './app.js' => 'app'
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
  const value = modulesFiles(modulePath)
  modules[moduleName] = value.default
  return modules
}, {})

const store = new Vuex.Store({
  modules,
  getters
})

export default store

getters.js
getters.js里面是所有你想对外报漏的数据

 

const getters = {
    name: state => state.user.name,
    phoneNo: state => state.user.phoneNo,
}
export default getters

user.js
login, logout, getInfo 相当于针对用户的一些api接口;(可以忽视掉)

state 里面储存的为用户token,name和phoneNo,其中在getters.js里面,可以实现了针对 user 模块内 name和phoneNo 数值的对外暴露

mutations 里面实现了重置用户信息,储存用户token,储存name,储存phoneNo的修改方法;

actions 里面是针对用户登录,获取用户信息,以及用户退出登陆的异步方法。此处你会看到有使用 Promise 异步操作,主要用于使用过程中的 await数据等待处理。 不太理解async/await 的可 参考此篇文章

namespaced: true,主要是为了解决不同模块命名冲突的问题,将不同模块的namespaced:true,之后在不同页面中引入getter、actions、mutations时,需要加上所属的模块名。

类似这样,就可以在使用页面内,直接对vuex内,user模块内的login用户登陆方法进行调用。
this.$store.dispatch("user/login");

 


import { login, logout, getInfo } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth'

const getDefaultState = () => {
    return {
        token: getToken(),
        name: "",
        phoneNo: "",
    }
}

const state = getDefaultState()

const mutations = {
    RESET_STATE: (state) => {
        Object.assign(state, getDefaultState())
    },
    SET_TOKEN: (state, token) => {
        state.token = token
    },
    SET_NAME: (state, name) => {
        state.name = name
    },
    SET_PHONENO: (state, phoneNo) => {
        state.phoneNo = phoneNo
    },
}

const actions = {
    // 用户登录,获取token,并储存到cookie里面
    login({ commit }, userInfo) {
        return new Promise((resolve, reject) => {
            commit('SET_PHONENO', '15518270529')
            resolve()
            // //调用登录接口
            // login().then(response => {
            //     const { data } = response
            //     // 储存到cookie里面
            //     commit('SET_TOKEN', data.token)
            //     setToken(data.token)
            //     resolve()
            // }).catch(error => {
            //     reject(error)
            // })
        })
    },
    //调用获取用户信息的接口
    getInfo({ commit, state }) {
        return new Promise((resolve, reject) => {
            //调用获取用户信息接口
            getInfo().then(response => {
                const { data } = response
                if (!data) {
                    reject('Verification failed, please Login again.')
                }
                const { name, phoneNo } = data
                commit('SET_PHONENO', phoneNo)
                commit('SET_NAME', name)
                resolve(data)
            }).catch(error => {
                reject(error)
            })
        })
    },
    //用户退出登录
    logout({ commit, state }) {
        return new Promise((resolve, reject) => {
            logout(state.token).then(() => {
                removeToken() // must remove  token  first
                commit('RESET_STATE')
                resolve()
            }).catch(error => {
                reject(error)
            })
        })
    },
}

export default {
    namespaced: true,
    state,
    mutations,
    actions
}

xxx.vue组件

 

import { mapGetters } from "vuex";

 

//计算属性
 computed:{
   //通过getter.js对外暴露的 phoneNo 值进行使用
   // {{phoneNo}} 数值使用
    ...mapGetters(['phoneNo'])
  },

 

  methods: {
    async isLogin() {
    //使用 try/catch 抓取错误信息,如果登陆失败则会输出错误信息,不往下执行
      try {
        await this.$store.dispatch("user/login");
        //如果登陆成功才会 输出 ‘登陆成功’
        console.log('登陆成功')
      } catch (error) {
        console.log(error);
      }
    }
  }

本面试题为前端常考面试题,后续有机会继续完善。我是歌谣,一个沉迷于故事的讲述者。

欢迎一起私信交流。


 

“睡服“面试官系列之各系列目录汇总(建议学习收藏)