构成
一个Vuex对象通常包括State, Getter, Mutation, Action这个几个属性。
const state = {}
const getters = {}
const mutations = {}
const actions = {}
export default new Vuex.Store({
state,
getters,
mutations,
actions
})
state是共享状态的集合,getters通过操作state获得派生状态,mutations是操作state数据的方法集合,actions让mutations中的方法能够在异步操作中起作用。
State: 状态
1. 声明
const state = {
todos: [
{ id: 1, text: 'breakfast', done: true },
{ id: 2, text: 'basketball', done: false },
{ id: 3, text: 'reading', done: false },
],
count: 0
}
2. 使用
Vuex中的状态存储是响应式的,读取Vuex状态一般用计算属性返回某个状态。比如:
computed: {
todos() {
return this.$store.state.todos;
},
count() {
return this.$store.state.count;
}
}
3. mapState
当有多个状态的时候,都声明为计算属性会显得冗余,我们可以通过mapState辅助函数来帮助我们生成计算属性。
import { mapState } from 'vuex'
export default {
// ...
computed: {
...mapState({
todos: state => state.todos,
count: state => state.count
})
}
}
或
import { mapState } from 'vuex'
export default {
// ...
computed: {
...mapState({
todos: 'todos', // 后面加引号的'todos'指的是state中的todos
count: 'count'
})
}
}
当计算属性名称与某个状态属性名相同时,可以简写为给mapState传一个字符串数组。比如:
import { mapState } from 'vuex'
export default {
// ...
computed: {
...mapState([
'todos',
'count'
])
}
}
Getter: 派生状态
1. 声明
如果我们需要从状态中派生出一些状态,比如对列表进行过滤:
computed: {
notTodos() {
return this.$store.state.todos.filter(item => !item.done);
}
}
如果有多个组件用到此属性,我们要么复制这个函数,或者抽取到一个共享函数然后在多处导入——无论哪种方式都不是很理想。
这时候就可以使用getter,如下:
// ...
const getters = {
notTodos: state => state.todos.filter(item => !item.done)
}
// ...
getter还可以接收其他getter作为第二个参数:
const getters = {
notTodos: state => state.todos.filter(item => !item.done),
notTodosLength: (state, getters) => getters.notTodos.length
}
2. 使用
然后在计算属性中使用getters获取即可:
computed: {
notTodos() {
return this.$store.getters.notTodos;
}
}
3. mapGetters
当有多个getter的时候,我们可以通过mapGetters辅助函数来帮助我们生成计算属性
computed: {
...mapGetters([
'notTodos',
'notTodosLength'
])
}
如果想给getter属性另取一个名字,可以使用对象形式
computed: {
// ...
...mapGetters({
notTodosList: 'notTodos',
notTodosLength: 'notTodosLength'
})
}
Mutation: 操作状态
注意:不建议在组件中直接对state进行操作,使用mutations来进行这些操作
mutation 必须是同步函数。
1. 声明
在mutations中定义一个addTodos方法:
const mutations = {
addTodos: (state, todo) => {
state.todos.push(todo);
}
}
2. 使用
在vue文件中就可以通过store.commit来调用:
methods: {
addTodos() {
let todo = { id: 4, text: 'writing', done: false };
this.$store.commit('addTodos', todo);
}
}
3. mapMutations
同样,当有多个mutation的时候,我们可以通过mapMutations辅助函数来帮助我们将方法映射为store.commit调用
methods: {
...mapMutations({
add: 'addTodos'
}),
handleClick() {
let todo = { id: 4, text: 'writing', done: false };
this.add(todo);
}
}
Action: 操作状态(异步)
注意:actions通过提交mutations来操作状态,而不是直接变更。
actions 可以包含任意异步操作。
1. 声明
注册一个action:
const mutations = {
addTodos: (state, todo) => {
state.todos.push(todo);
}
}
const actions = {
addTodos: (context, todo) => {
context.commit('addTodos', todo);
}
}
通过参数结构可简化为:
const mutations = {
addTodos: (state, todo) => {
state.todos.push(todo);
}
}
const actions = {
addTodos: ({ commit }, todo) => {
commit('addTodos', todo);
}
}
2. 使用
methods: {
handleClick() {
let todo = { id: 5, text: 'driving', done: false };
this.$store.dispatch('addTodos', todo);
}
}
3. mapActions
同样,当有多个action的时候,我们可以通过mapActions辅助函数来帮助我们将方法映射为store.dispatch调用
methods: {
...mapActions({
add: 'addTodos'
}),
handleClick() {
let todo = { id: 5, text: 'driving', done: false };
this.add(todo);
}
}
对于复杂操作,action可以返回一个Promise对象,比如:
const actions = {
addTodos: ({ commit }, todo) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('addTodos', todo);
resolve();
}, 1000)
})
}
}
这样就可以:
methods: {
handleClick() {
let todo = { id: 5, text: 'driving', done: false };
this.$store.dispatch('addTodos', todo).then(() => {
// ...
})
}
}
参考:https://vuex.vuejs.org/zh/