本文主要介绍如何使用vuex的modules将状态数据根据不同模块进行划分并分别管理以及如何使用mapGetters快速将状态管理中的数据导入成local变量。
文章目录
- 本系列前文传送门
- 一、场景说明
- 二、使用modules划分不同模块
- 三、使用Getters获取状态管理数据
- Getter传参
- mapGetters 辅助函数
vuex
用于vue
开发过程中的数据管理,但随着网站功能增多,项目规模变大,需要管理的数据也自然会越来越多。如果我们把所有的数据都放在一起,那么在后期开发过程可能会导致数据混淆(比如命名相似),或者是代码集中在一处难以维护。
所以我们可以考虑将数据根据功能或者场景划分成不同模块,比如登录模块Login
,然后使用modules
关键字将不同模块放入到store
中。
modules
的用法其实很简单,如下:
const moduleA = {
state: {
name: "A",
},
mutations: {},
actions: {},
getters: {}
}
const moduleB = {
state: {
name: "B",
},
mutations: {},
actions: {}
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
console.log(store.state.a.name) // -> `moduleA`'s state
console.log(store.state.b.name) // -> `moduleB`'s state
我们在上述代码中定义了两个不同的模块来储存不同场景的模块数据,在moduleA
中变量name
的值为A
,在moduleB
中变量name
的值为B
。
定义好各个模块后,我们在store
中放入字段名
到具体模块
的对应关系,{a: moduleA, b: moduleB}
。之后我们就可以通过store.state.a
访问到a
(即moduleA
)中的state
,通过store.state.b
访问到b
(即moduleB
)中的state
。
所以我们就可以通过store.state.b.name
获取到moduleB
中state
的name
字段,返回值为B
。
进一步,我们可以把moduleB
的代码独立成文件,比如独立到moduleB.store.js
中,然后导入到一个总入口,比如store.js
,达到跟业务逻辑代码一样模块化的效果。
有时候我们需要基于store
中的state
进行一些计算。比如我们写一个清单应用,有一个todo-list,需要对列表进行过滤并计数:
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length
}
}
同样地,如果在多处都需要使用,那么我们要么要复制粘贴同一份代码,这让代码变得冗余;要么我们把这个计算放到store
的方法中供每个地方调用,这样调用时需要使用commit()
方式比较不便,并且可能因为重复计算影响性能。
所以vuex
允许我们在store
中定义getter
(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。并且我们在访问时也可能像访问寻常变量一样访问它们。如下:
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
于是我们就可以通过store.getters.doneTodos
获取数据,得到[{ id: 1, text: '...', done: true }]
在其他组件中,也可以直接在computed
属性中获取这些数据,如下:
computed: {
doneTodosCount () {
return this.$store.getters.doneTodosCount
}
}
getter
也可以返回一个函数,我们用函数调用的方式来把参数传到getter
的处理逻辑中,如下:
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
在其他组件中,就可以有如下调用:
this.$store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
mapGetters
辅助函数只有一个简单但实用的作用:将store
中的getter
映射到局部计算属性,如下:
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
上述代码就可以直接帮助我们得到同名计算属性: doneTodosCount
,anotherGetter
如果我们希望重命名getter
,则可以传入对应关系,如下:
...mapGetters({
// 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})
熟悉了以上这些内容之后,基本就可以应对状态管理的常见场景,清晰地组织状态管理代码,避免随着项目规模变大后代码耦合影响开发效率。
写文不易,如果对你有帮助的话,来一波点赞、收藏、关注吧~