此篇文章是介绍利用 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);
}
}
}
本面试题为前端常考面试题,后续有机会继续完善。我是歌谣,一个沉迷于故事的讲述者。
欢迎一起私信交流。