使用vuex管理用户信息

介绍

本文介绍如何使用vuex管理用户信息,封装相关方法,为所有页面提供接口,并将其应用在路由检测中的方法。

Vuex 结构

前置工作

新建一个store.js文件,将以下代码复制到文件

1
2
3
4
5
6
7
8
9
10
11
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
getters: {}
})

在main.js中添加

1
2
3
4
5
6
7
import store from './store'

new Vue({
...
store,
...
)}

这样我们就能在任意页面使用vuex store了

结构说明

从上面的代码可以看出,vuex store的结构分为四个部分:state,mutation,actions,getter

  • state:存储变量的地方,可以理解成是vuex store的公有成员变量;
  • mutations:是更新state的地方;
  • actions:触发mutation的地方,同时也是定义vuex store方法的地方;
  • getter:提供计算属性的地方,主要作用是提高便捷性;

vuex store的一般用法为:在state中存储信息,外部通过调用action中的方法来触发mutation,在mutation中对state进行修改,最终外部页面通过state或者getter获取数据。

使用vuex进行登录

现在以用户登录为例说明vuex store的用法。

我们先在state里定义要存储的内容,在这里存储用户登录状态与用户信息。需要注意的是,vuex存储的变量是非持久化的,刷新页面、退出页面都会丢失state中的值。我们就需要使用localStorage辅助,进行变量持久化存储。这样下一次用户打开页面时,如果用户的cookie还有效,用户就能直接进入主页,无需再次登录。

1
2
3
4
5
6
7
const STATUS_ID = "status"

state:
{
status: localStorage.getItem(STATUS_ID),
user : {},
}

在mutation中定义两个改变state的mutaions,一个用于登录成功的情况,另一个用于登录失败的情况

1
2
3
4
5
6
7
8
9
signin_success(state, user)
{
state.status = 'success'
state.user = user
},
signin_error(state)
{
state.status = 'error'
},

在action中编写signin函数,供外部调用。在action中,我们应该返回一个promise,支持调用者处理成功或失败的情况。

1
2
3
4
5
6
7
8
9
10
11
signin({commit, dispatch}, user)
{
return new Promise((resolve, reject) =>
{
//网络请求('/signin', user)
// if 成功
commit('signin_success', response.user)
// else
commit('signin_error')
})
},

最后完成getter部分,返回一个bool值,提供用户是否登录成功的信息,免去外部页面使用字符串判断的麻烦。

1
2
3
4
getters :
{
isSignedIn: state => state.status == 'success',
}

在登陆页面只需简单地分发任务(dispatch),就能完成登陆功能。(在前置工作中已经让store全局化了)

1
this.$store.dispatch("signin", form).then(...).catch(...)

执行这一语句后发生的事情如下

vuex应用

提供用户信息

获取登录状态

1
this.$store.getters.isSignedIn

获取用户信息

1
this.$store.state.user

辅助路由检测

在vue应用中,有一些页面需要登陆才能访问,这个功能可以通过vuex与vue router的beforeEach来实现。

通过匹配router目标路径,并使用vuex store判断用户是否已经登陆,来实现阻止跳转和重定向的功能。以下代码的逻辑时,未登陆的用户只能访问登陆注册页,登陆用户能访问所有页面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
router.beforeEach((to, from, next) =>
{
// router guard

if (to.path != '/signin' && to.path != '/signup')
{
if (store.getters.isSignedIn)
next()
else
// if the user has not signen in,
// he can only visit signin and signup
next('/signin')
}
else
next()
})

源代码

包含了登陆、注册、登出逻辑的完整代码(省去的网络请求部分)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const STATUS_ID = "status"

export default new Vuex.Store({
state:
{
status: localStorage.getItem(STATUS_ID),
user : {},
},
mutations:
{
signin_request(state)
{
state.status = 'loading'
},
signin_success(state, user)
{
state.status = 'success'
state.user = user
},
signin_error(state)
{
state.status = 'error'
},
signout(state)
{
state.status = localStorage.removeItem(STATUS_ID)
state.user = {}
},
},
actions:
{
signin({commit, dispatch}, user)
{
return new Promise((resolve, reject) =>
{
commit('signin_request')

//网络请求
// if 成功
commit('signin_success', response.user)
// else
commit('signin_error')

})
},
signup({commit}, user)
{
return new Promise((resolve, reject) =>
{
//网络请求
})
},
signout({commit})
{
return new Promise((resolve, reject) =>
{
//网络请求
commit('signout')
})
},
},
getters :
{
isSignedIn: state => state.status == 'success',
}
})