Vue状态管理工具Vuex
通过createStore创建一个store实例
import { createApp } from 'vue'
import { createStore } from 'vuex'
// 创建一个新的 store 实例
const store = createStore({
state() {
return {
count: 0
}
},
mutations: {
increment(state) {
state.count++
}
}
})
const app = createApp({
/* 根组件 */
})
// 将 store 实例作为插件安装
app.use(store)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 核心概念
# state
在 Vue 组件中,可以使用this.$store访问store实例,访问状态使用this.$store.state.count。
原理是 app.use(store)的时候,将 store 实例挂在到 Vue 原型上,重命名为$store,因此每个 Vue 组件实例都可以访问 store 实例
可以使用 mapState 辅助函数来进行映射
import { mapState } from 'vuex'
export default {
computed: {
...mapState({
// 箭头函数可使代码更简练
count: state => state.count,
// 传字符串参数 'count' 等同于 `state => state.count`
countAlias: 'count',
// 为了能够使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
})
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。
computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])
2
3
4
# Getter
Getter 相当于 state 的计算属性,会添加到响应式缓存中。
# 定义 Getters
getters: {
// ...
doneTodosCount (state, getters) {
return getters.doneTodos.length
}
}
2
3
4
5
6
# 获取 Getters
- 通过属性访问
在 Vue 组件中可以通过,this.$store.getters.doneTodos来访问
- 通过方法访问
- mapGetters
# Mutation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,使用this.$store.commit('increment', 10)来提交 mutation
mutation 必须是同步函数,目的是只有是同步函数,devtools 才能跟踪到状态的改变。所以这里使用异步也是可以执行的,可能会有警告,但不是绝对禁止。
# action
Action 类似于 mutation,二者几乎一模一样,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
action 采用 dispatch 来派发,this.$store.dispatch('increment')
# 项目结构
需要遵守的规则:
应用层级的状态应该集中到单个 store 对象中。
提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
异步逻辑都应该封装到 action 里面。
对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:
├── index.html
├── main.js
├── api
│ └── ... # 抽取出API请求
├── components
│ ├── App.vue
│ └── ...
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── cart.js # 购物车模块
└── products.js # 产品模块
2
3
4
5
6
7
8
9
10
11
12
13
14
# 组合式 API
可以通过调用 useStore 函数,来在 setup 钩子函数中访问 store。这与在组件中使用选项式 API 访问 this.$store 是等效的。
import { useStore } from 'vuex'
export default {
setup() {
const store = useStore()
}
}
2
3
4
5
6
7
# 访问 State 和 Getter
import { computed } from 'vue'
import { useStore } from 'vuex'
export default {
setup() {
const store = useStore()
return {
// 在 computed 函数中访问 state
count: computed(() => store.state.count),
// 在 computed 函数中访问 getter
double: computed(() => store.getters.double)
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 访问 Mutation 和 Action
import { useStore } from 'vuex'
export default {
setup() {
const store = useStore()
return {
// 使用 mutation
increment: () => store.commit('increment'),
// 使用 action
asyncIncrement: () => store.dispatch('asyncIncrement')
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15