Vuex
Vuex是什么?
Vuex是一个专为Vue.js开发的状态管理模式+库,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
最简单的Store
安装Vuex后,先创建一个store
,仅需要提供一个初始state
对象和一些mutation
:
1 | // @/src/utils/store.js |
然后在main.js
中使用它:
1 | import { createApp } from 'vue' |
现在可以通过 store.state
来获取状态对象,并通过 store.commit
方法触发状态变更:
1 | store.commit('increment') |
在组件中可以通过this.$store
访问store
:
1 | methods: { |
State
在Vue组件中获得Vuex状态
Vuex通过Vue的插件系统将store
实例从根组件中注入到所有的子组件里。且子组件能通过this.$store
访问到。
1 | const Counter = { |
mapState
辅助函数
当一个组件需要获取多个状态时,将这些状态都声明为计算属性会显得冗余,我们可以使用mapState
函数生成计算属性:
1 | import { mapState } from 'vuex' |
当要映射的计算属性与state
的子节点名称相同时,我们可以给mapState
传一个字符串数组:
1 | computed: mapState([ |
使用对象展开运算符,我们可以把mapState
返回的对象与其他局部计算属性一起混用:
1 | computed: { |
Getter
Getter
可以认为是store
的计算属性。
Getter
接受state
为其第一个参数:
1 | const store = createStore({ |
通过属性访问
Getter
会暴露为 store.getters
对象,可以以属性的形式访问这些值。
1 | store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }] |
可以在组件中使用Getter:
1 | computed: { |
通过方法访问
Getter
可以返回一个函数来实现给Getter
传参。
1 | getters: { |
1 | store.getters.getTodoById(2) |
mapGetters
辅助函数
mapGetters
辅助函数仅仅是将store
中的getter
映射到局部计算属性:
1 | import { mapGetters } from 'vuex' |
如果想将一个getter
属性另取一个名字,使用对象形式:
1 | ...mapGetters({ |
Mutation
更改Vuex的store
中的状态的唯一方法是提交mutation
。一个mutation
有一个字符串的数据类型和一个回调函数,回调函数就是修改state
的地方。mutation
以state
做为它的第一个参数:
1 | const store = createStore({ |
调用mutation
时,要调用store.commit
方法:
1 | // 将type写成字符串的写法,只会把第二个参数当成payload |
提交Payload
可以向store.commit
传入额外的参数,即mutation
的payload:
1 | mutations: { |
1 | store.commit('increment', 10) |
在组件中提交Mutation
可以在组件中使用 this.$store.commit('xxx')
提交mutation
,或者使用 mapMutations
辅助函数将组件中的methods
映射为store.commit
调用。
1 | import { mapMutations } from 'vuex' |
Action
Action
类似于mutation
,不同在于Action
提交的是mutation
,并且Action
可以包含异步操作。注册一个简单的Action
:
1 | actions: { |
Action
函数接受一个与store
实例具有相同方法和属性的context
对象,因此可以在action
里通过context.commit
提交一个mutation
,或者通过context.state
和context.getters
来获取 state
和 getters。
可以使用ES6的参数解构来简化代码
1 | increment = ({ commit }) => { |
分发Action
Action
通过store.dispatch
触发:
1 | store.dispatch('increment') |
Action
类似Mutation
,支持同样的Payload方式和对象方式分发:
1 | // 以payload形式分发 |
在组件中分发Action
在组件中可以使用this.$store.dispatch
分发action,或者使用mapActions
将action
映射到组件的methods
中。
组合Action
store.dispatch
可以处理被触发的action
的处理函数返回的Promise
,并且store.dispatch
仍然返回Promise:
1 | actionA ({ commit }) { |
接下来可以链式调用:
1 | store.dispatch('actionA').then(() => { |
在另一个Action
中也可以:
1 | actions: { |
结合async
/await
,可以优化结合action
的代码:
1 | actions: { |
表单处理
在表单上对属于Vuex的store
使用v-model
会比较棘手:
1 | <input v-model="obj.message"> |
因为store
的state
只能通过触发mutation
改变,直接通过v-model
改变,会抛出错误。用常规的思维解决这个问题的方法是:给input
表情绑定value
,然后监听input
或者change
事件,在事件回调中触发mutation
使事件改变。
这样做来修改数据太麻烦了,并且损失了v-model
中很多方便的特性,下面是另一种修改的方法:在计算属性中提供set
方法,然后再set
方法中触发mutation
:
1 | <input v-model="message"> |
1 | computed: { |