您的当前位置:首页正文

vuex的应用场景

来源:独旅网
vuex的应⽤场景

vuex 作为 vue ⽣态中⽤于状态管理的⼀种模式,已被⼴泛应⽤于 vue 单页应⽤开发中。下⾯谈谈⾃⼰对 vuex 的⼀些个⼈见解以及在实际项⽬中的应⽤场景。

vuex 的⼏个核⼼概念Store:Vuex 使⽤⼀个 Store 对象管理应⽤的状态,⼀个 Store 包括 State, Getter, Mutation, Action 四个属性。State:State 意为“状态”,是 vuex 状态管理的数据源,我个⼈觉得相当于数据库。

Getter:Getter 的作⽤与 filters 有⼀些相似,可以将 State 进⾏过滤后输出。(参考:https://www.jb51.net/article/159727.htm)

1 应⽤场景

假设我们在 Vuex 中定义了⼀个数组1

const store = new Vuex.Store({2 state: {

3 list:[1,3,5,7,9,20,30]4 }5 ...})6

业务场景希望过滤出⼤于 5 的数。马上想到的⽅法可能的是:在组件的计算属性中进⾏过滤:1

2615效果:

功能虽然实现了,但如果其它组件也需要过滤后的数据,那么就得把 index.vue 中的计算过滤代码复制出来。如果过滤规则发⽣变化,还得⼀⼀修改这些组件中的计算属性,很难维护。这种场景下,我们就可以使⽤ getters 属性啦O(∩_∩)O~2 基础⽤法main.js:

1

2const store = new Vuex.Store({3 state: {

list: [1, 3, 5, 7, 9, 20, 30]4 },

5 getters: {

6 filteredList: state => {

7 return state.list.filter(item => item > 5)8 } }9})10

index.vue:123456

10

效果达到了,⽽且只需要在⼀处维护过滤规则即可。3 内部依赖

getter 可以依赖其它已经定义好的 getter。⽐如我们需要统计过滤后的列表数量,就可以依赖之前定义好的过滤函数。main.js:

1

2const store = new Vuex.Store({3 state: {

4 list: [1, 3, 5, 7, 9, 20, 30]5 },

6 getters: {

filteredList: state => {

7 return state.list.filter(item => item > 5)8 },

9 listCount: (state, getters) => {10 return getters.filteredList.length;11 }12 }})13

index.vue:

12

310

1122效果:

Mutation:Mutaion 是 vuex 中改变 State 的唯⼀途径(严格模式下),并且只能是同步操作。

Action:⼀些对 State 的异步操作和业务逻辑操作可以放在 Action 中,并通过在 Action 提交 Mutaion 变更状态。(下⾯⽤户登录和⽤户信息demo)

Module:当 Store 对象过于庞⼤时,可根据具体的业务需求分为多个 Module。

关于⽤户登录和⽤户信息模块的module

1 import storage from 'store'

2 import { login, getInfo, logout } from '@/api/login'

见 3 import { ACCESS_TOKEN } from '@/store/mutation-types' 4 import { welcome } from '@/utils/util' 5 import Vue from 'vue' 6

7 const user = { 8 state: { 9 token: '', 10 name: '', 11 welcome: '', 12 avatar: '', 13 roles: [], 14 info: {} 15 }, 16

17 mutations: {

18 SET_TOKEN: (state, token) => { 19 state.token = token 20 },

21 SET_NAME: (state, { name, welcome }) => { 22 state.name = name

23 state.welcome = welcome 24 },

25 SET_AVATAR: (state, avatar) => { 26 state.avatar = avatar 27 },

28 SET_ROLES: (state, roles) => { 29 state.roles = roles 30 },

31 SET_INFO: (state, info) => { 32 state.info = info 33 } 34 }, 35

36 actions: { 37 // 登录

38 Login({ commit }, userInfo) {

39 return new Promise((resolve, reject) => { 40 login(userInfo).then(response => { 41 const result = response.result

42 storage.set(ACCESS_TOKEN, result.token, 7 * 24 * 60 * 60 * 1000) 43 commit('SET_TOKEN', result.token) 44 resolve()

45 }).catch(error => { 46 reject(error) 47 }) 48 }) 49 }, 50

51 // 获取⽤户信息

52 GetInfo({ commit }) {

53 return new Promise((resolve, reject) => { 54 getInfo().then(response => { 55 const result = response.result 56

57 if (result.role && result.role.permissions.length > 0) { 58 const role = result.role

59 role.permissions = result.role.permissions 60 role.permissions.map(per => {

61 if (per.actionEntitySet != null && per.actionEntitySet.length > 0) {

62 const action = per.actionEntitySet.map(action => { return action.action }) 63 per.actionList = action 64 } 65 })

66 role.permissionList = role.permissions.map(permission => { return permission.permissionId }) 67 commit('SET_ROLES', result.role) 68 commit('SET_INFO', result) 69 } else {

70 reject(new Error('getInfo: roles must be a non-null array !')) 71 } 72

73 commit('SET_NAME', { name: result.name, welcome: welcome() }) 74 commit('SET_AVATAR', result.avatar) 75

76 resolve(response) 77 }).catch(error => { 78 reject(error) 79 }) 80 }) 81 }, 82

83 // 登出

84 Logout({ commit, state }) {

85 return new Promise((resolve) => { 86 logout(state.token).then(() => {

87 resolve()

88 }).catch(() => { 89 resolve()

90 }).finally(() => {

91 commit('SET_TOKEN', '') 92 commit('SET_ROLES', [])

93 storage.remove(ACCESS_TOKEN) 94 }) 95 }) 96 } 97 98 } 99 }100

101 export default user

每个module下state⾥的数据,绑定到根store上

const getters = {

isMobile: state => state.app.isMobile, lang: state => state.app.lang, theme: state => state.app.theme,

qualityCheckInfo: state => state.app.qualitycCheckBaseInfo, color: state => state.app.color, token: state => state.user.token, avatar: state => state.user.avatar, nickname: state => state.user.name, welcome: state => state.user.welcome, roles: state => state.user.roles, userInfo: state => state.user.info,

addRouters: state => state.permission.addRouters, multiTab: state => state.app.multiTab}

export default getters

导出store的index.js⽂件

1 import Vue from 'vue' 2 import Vuex from 'vuex' 3

4 import app from './modules/app' 5 import user from './modules/user' 6

7 // default router permission control

8 import permission from './modules/permission' 9

10 // dynamic router permission control (Experimental)11 // import permission from './modules/async-router'12 import getters from './getters'13

14 Vue.use(Vuex)15

16 export default new Vuex.Store({17 modules: {18 app,19 user,

20 permission21 },

22 state: {23 24 },

25 mutations: {26 27 },

28 actions: {29 30 },

31 getters32 })

上图为官⽹中 vuex 各个要素的关系图,总的来说,我们可以在组件中触发 Action,Action 则会提交 Mutation,Mutaion 会对 State 进⾏修改,组件再根据 State 、Getter 渲染页⾯。

什么样的应⽤场景下需要 vuex ?如果不打算开发⼤型单页应⽤,使⽤ Vuex 可能是繁琐冗余的。确实是如此——如果你的应⽤够简单,那最好不要使⽤ Vuex。⼀个简单的 global event bus 就⾜够所需了。但是,如果需要构建是⼀个中⼤型单页应⽤,很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为⾃然⽽然的选择。

vuex ⼀般⽤于中⼤型 web 单页应⽤中对应⽤的状态进⾏管理,对于⼀些组件间关系较为简单的⼩型应⽤,使⽤ vuex 的必要性不是很⼤,因为完全可以⽤组件 prop 属性或者事件来完成⽗⼦组件之间的通信,vuex 更多地⽤于解决跨组件通信以及作为数据中⼼集中式存储数据。使⽤ vuex 解决跨组件通信问题

跨组件通信⼀般指⾮⽗⼦组件间的通信,⽗⼦组件的通信⼀般可以通过以下⽅式:1、通过 prop 属性实现⽗组件向⼦组件传递数据2、通过在⼦组件中触发事件实现向⽗组件传递数据

⾮⽗⼦组件之间的通信⼀般通过⼀个空的 Vue 实例作为 中转站,也可以称之为 事件中⼼、event bus。// 创建事件中⼼实例let bus = new Vue()// 在组件 A 中触发事件bus.$emit('test', 1)// 在组件 B 中接受事件bus.$on('test', (id) => {// ...})

采⽤ event bus 的⽅式适合简单的跨组件事件触发,对于多层级组件嵌套等较为复杂的场景,使⽤ vuex 能更好地应对。vuex 是通过将

state 作为数据中⼼、各个组件共享 state 实现跨组件通信的,此时的数据完全独⽴于组件,因此将组件间共享的数据置于 State 中能有效解决多层级组件嵌套的跨组件通信问题。

vuex 作为数据存储中⼼

vuex 的 State 在单页应⽤的开发中本⾝具有⼀个“数据库”的作⽤,可以将组件中⽤到的数据存储在 State 中,并在 Action 中封装数据读写的逻辑。这时候存在⼀个问题,⼀般什么样的数据会放在 State 中呢? ⽬前主要有两种数据会使⽤ vuex 进⾏管理:1、组件之间全局共享的数据2、通过后端异步请求的数据

本⼈所在团队在实际的项⽬开发过程中更多的是应⽤第⼆种,即把通过后端异步请求的数据都纳⼊ vuex 状态管理,在 Action 中封装数据的增删改查等逻辑,这样可以⼀定程度上对前端的逻辑代码进⾏分层,使组件中的代码更多地关注页⾯交互与数据渲染等视图层的逻辑,⽽

异步请求与状态数据的持久化等则交由 vuex 管理。

总结:vuex 具体应⽤在哪取决于项⽬的规模以及具体的业务场景,可能是为了解决多层嵌套组件之间的通信问题,或是为了更好地管理应⽤中错综复杂的状态关系,⽽不能为了⽤ vuex ⽽在项⽬中使⽤ vuex。

参考: https://zhuanlan.zhihu.com/p/41237859

见下⾯⽤户登录和⽤户信息demo

因篇幅问题不能全部显示,请点此查看更多更全内容