前端废物的自救之路(3)使用Cookie完成Nuxt.js中Vuex的持久化
为什么需要Vuex持久化
在开发的过程中,我们会使用Vuex来存储用户信息、Token等内容,但Vuex的信息是存储在内存中的,当页面刷新时,内容自然就丢失了。我们需要寻找其他的办法使得刷新页面时Vuex的信息能保存下来,也就是Vuex的持久化。
Nuxt.js中的Vuex持久化方案及其可用性
使用Vue.js
时,我们一般用vuex-persist
、vuex-persistedstate
等框架完成Vuex的持久化,也并不会出什么问题。但是在Nuxt中,情况就不一样了。
在搜索引擎上搜索Nuxt Vuex持久化
,可以找到以下解决方案:
-
vuex-persistedstate
配合js-cookie
-
可用性:不可用,按照文中的方法配置仍然出现找不到
window
对象的情况。在配置插件的时候配置了ssr: false
,仍然找不到window对象,推测可能是Nuxt
或Vuex
的版本问题(注:这篇文章是19年12月的)。
-
vuex-persist
-
可用性:部分可用,配置完成之后不会出现找不到
window
对象的情况。此方法在除了asyncData
之外的方法中都是可用的,但是asyncData
方法中并不能访问到localStorage
(因为asyncData方法是在服务端执行的,没有localStorage),所以如果不需要在asyncData
中使用Vuex的话可以采用这样的方案。 -
相关文章:Nuxt.js with vuex-persist - persisted state not available in asyncData upon page refresh
-
nuxtServerInit
方法配合cookie-universal-nuxt
- 地址:vuex状态持久化在vue和nuxt.js中的区别
- 可用性:不可用。会提示
$cookies
对象为undefined
。推测可能是Cookie的设置问题。
终极解决方案:js-cookie配合nuxtServerInit实现Vuex持久化
常见的解决方案都不可用,那么我们就需要终极解决方案:js-cookie
配合nuxtServerInit
。
- 地址:nuxt刷新页面Vuex失效,在axios中使用vuex【vuex-persist,localStorage,Cookie。三种办法解决】中的第三种。
- 可用性:完全可用,但是有一点麻烦(因为要解析Cookie的字符串),但是相比不可用和部分可用已经是很大的进步了。
实现起来也是很简单的。
第一步:安装js-cookie
npm install --save js-cookie
第二步:设置Vuex时同时设置Cookie
以登录为例,在拿到用户信息后使用js-cookie
把用户信息设置到Cookie中。注意Cookie的过期时间要和服务端设置的Token的过期时间保持一致(服务端设置Token的过期时间是4小时),否则Token过期后再访问需要认证的页面会出现循环重定向的问题(我配置了根据Cookie判断用户是否登录的逻辑,并且登录后再访问登录页面会被重定向到后台管理,所以才会出现这样的问题,当然如果没有做这样的配置的话就无所谓了,或者你也可以配置在Token失效后清除Cookie的操作)。
注意expires
属性的单位是天,如果需要设置为小时的话可以传入小数。
@/pages/login.vue
import { mapMutations } from 'vuex'
import * as Cookies from 'js-cookie'
export default {
// ...
methods: {
...mapMutations(['setUserInfo']),
login () {
this.$refs.loginForm.validate((valid) => {
if (valid) {
// 表单校验通过,开始登录
this.$axios.post('/login', {
username: this.form.username,
password: this.form.password
}).then((res) => {
// 登录成功,向Vuex中设置用户信息
this.setUserInfo({
token: res.token,
userId: res.id,
username: res.username
})
// Cookie的过期时间与Token的过期时间一致,为4小时
Cookies.set('token', res.token, { expires: 1 / 6 })
Cookies.set('userId', res.user_id, { expires: 1 / 6 })
Cookies.set('username', res.username, { expires: 1 / 6 })
this.$router.push('/admin')
}).catch((err) => {
this.msg = err.response.data.message
})
} else {
return false
}
})
},
// ...
}
}
第三步:设置Vuex
我们刚刚设置了保存Cookie的逻辑,接下来就需要把Cookie的信息取出来,设置在Vuex中,完成持久化操作。
nuxtServerInit
方法在每次发送请求且请求未到达页面的时候都会被调用,可以借助这个方法来设置Vuex。
@/store/index.js
export const state = () => ({
token: '',
userId: 0,
username: ''
})
export const mutations = {
// 用户登录时,需要设置用户信息
setUserInfo (state, loginInfo) {
state.token = loginInfo.token
state.userId = loginInfo.userId
state.username = loginInfo.username
},
// 用户登出时,需要删除用户信息
removeUserInfo (state) {
state.token = ''
state.username = ''
state.userId = 0
}
}
export const actions = {
nuxtServerInit ({ commit, store }, { req }) {
// 切分Cookie
const cookie = req.headers.cookie.split(';')
// 定义字符常量:需要从cookie中取出的值的名称
const tk = 'token='
const un = 'username='
const uid = 'userId='
// 需要持久化的值
let token = ''
let username = ''
let userId = 0
// 遍历Cookie,取得需要的值
cookie.forEach((e) => {
if (e.includes(tk)) {
token = e.split(tk)[1]
} else if (e.includes(un)) {
username = e.split(un)[1]
} else if (e.includes(uid)) {
userId = e.split(uid)[1]
}
})
// 提交mutation
commit('setUserInfo', {
token,
username,
userId
})
}
}
注意这里我为了解决使用传统写法时控制台报Warn的问题而采用了Nuxt建议的写法。
设置完成并重启应用之后,再次刷新页面就不会出现vuex数据被清空而需要重新登录的问题了。
网友评论