上一篇文章,我们通过localstorage和axios拦截器实现了账号鉴权。
但是 localstorage 作为永久化存储,即使用户关闭浏览器,它还会存在,第二次打开系统已保存的用户token还是存在。所以,注定了不能作为真正的用户鉴权的一份子。
那么,谁可以替代呢?正是我们今天要引入的 Vuex ,它是保存在内存中的数据仓库(个人喜欢这么称呼),在系统关闭后会被清空,那么当用户二次打开系统时,就会判定为待登录状态。再加上vuex响应式的原理,更能支持后期我们其它需要存储的数据同步等。所以,vuex是最佳方案。
安装
npm install vuex@next --save
这里推荐安装最新的4.0版本,它为vue3.0做了许多适配(或者说是配套)。
创建store.js文件,并引入vuex
import { createStore } from 'vuex'
// 创建一个新的 store 实例
const store = createStore({
state () {
return {
accessToken: ''
}
},
mutations: {
saveToken (state,accessToken) {
state.accessToken = accessToken
}
}
})
export default store
这里创建了个accessToken ,作为存储登录后获取到的用户accessToken
使用
定义好仓库以后,可以在main.js全局引入它:
import store from './store/store'
app.use(store)
vuex绑定了全局属性,我们全局引入以后,可以使用this.$store来调用创建好的仓库。
那么接下来就是改造登录回调的方法了,在login.vue里面我们做如下修改:
loginByUsername(this.name, md5(this.pwd)).then((res) => {
// 取消localStorage保存token的方法
// localStorage.setItem("accesstoken",res.data.access_token)
this.$store.commit('saveToken',res.data.access_token)
console.log('打印保存的token')
console.log(this.$store.state.accessToken)
});
然后在系统中登录测试一下,可以看到成功打印了我们保存的token:
接下来就是在axios拦截器(参考上一篇文章)对header赋值:
// 这里需要引入store
import store from '/src/store/store'
// 添加请求拦截器
axios.interceptors.request.use(
(config) => {
let accesstoken = store.state.accessToken;
if (accesstoken) {
config.headers["accesstoken"] = store.state.accessToken;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
这样我们就通过vuex实现了鉴权流程。
模块化仓库()
经过上面登录接口调用,不但会返回用户token,同时还会返回用户数据如,id等。此外在系统开发过程中,同样面临很多临时存放数据的场景(如购物车)。
这种情况简单的方法,就是在store.js文件里增加state状态和相应方法即可。但是,随着系统体积越来越庞大,导致store.js文件代码量会越来越臃肿,后期维护会相当困难。
所以vuex提供了将store分割的工具,即模块化仓库。
首先我们创建一个user.js,并按照vuex标准方式定义state:
const user = {
state() {
return {
userInfo: {},
};
},
mutations: {
saveUser(state, userInfo) {
state.userInfo = userInfo;
},
},
};
export default user;
这里定义了个对象userInfo,用于接收用户数据。
然后把user用到store.js中:
import { createStore } from "vuex";
import user from "./user";
// 创建一个新的 store 实例
const store = createStore({
state() {
return {
accessToken: "",
};
},
mutations: {
saveToken(state, accessToken) {
state.accessToken = accessToken;
},
},
modules: {
user,
},
});
export default store;
可以看到,注入modules的同时,本身的state依然可以使用,两者可以共存。
然后改造一下login.vue的代码:
loginByUsername(this.name, md5(this.pwd)).then((res) => {
// 取消localStorage保存token的方法
// localStorage.setItem("accesstoken",res.data.access_token)
this.$store.commit('saveToken',res.data.access_token)
console.log('打印保存的token')
console.log(this.$store.state.accessToken)
this.$store.commit('saveUser',res.data)
console.log('打印保存的user')
console.log(this.$store.state.user.userInfo.nick_name)
});
登录成功后直接调用saveUser保存用户数据,最终打印的结果:
模块化作为前端的主流思想,非常推荐大家使用modules去定义状态。