vuex中的核心概念:
state Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
mutations 定义的方法动态修改Vuex 的 store 中的状态或数据。
getters 类似vue的计算属性,主要用来过滤一些数据。
actions 可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。
view 层通过 store.dispath 来分发 action。
简单创建一个vuex实例:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
increment(context) {
context.commit('increment')
}
}
})
实战应用:
vuex中有两个辅助函数:
1:mapGetters
辅助函数:
mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:
实战应用:
import { mapGetters } from 'vuex'
export default {
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
])
}
}
那么在我们没用mapGetters之前,我们可以通过什么访问到state中的数据呢?
例如在一个vuex实例中:
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)
}
}
})
Getter 会暴露为 store.getters 对象,你可以以属性的形式访问这些值:
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
Getter也可以接受其他 getter 作为第二个参数:
例如修改一下vuex实例中的 getters:
getters: {
// ...
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
store.getters.doneTodosCount // -> 1
你也可以通过让 getter 返回一个函数,来实现给 getter 传参:
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
2:mapState
辅助函数:
当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键:
总结:
1.当一个组件只是需要一个state中的状态的时候,写法如下:
computed : mapState({
fenlei : (state)=> state.fenlei
})
2:当一个组件需要获取多个状态的时候,有两种写法:
1) 可以使用 ... 扩展运算符将对象展开
computed : {
... mapState({
fenlei : (state)=> state.fenlei
// 注: 红色 fenlei为页面data中定义的状态值, 蓝色fenlei为vuex state中定义的状态变量
})
}
2) 简写形式:
computed : {
... mapState( [ ' fenlei ' ] ) // 注: fenlei 为vuex state中定义的状态变量
}
vuex中的Action 通常是异步的,如何知道 action 什么时候结束?如何组合多个 action,以处理更加复杂的异步流程?
首先,你需要明白 store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise:
actions: {
actionA({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('increment')
resolve()
}, 1000)
})
}
}
在dispatch投递任务使用的时候就可以使用 .then() 或 .catch()了。
store.dispatch('actionA').then(() => {
// ...
})
在另外一个 action 中也可以使用.then()
actions: {
// ...
actionB({ dispatch, commit }) {
return dispatch('actionA').then(() => {
commit('increment')
})
}
}
最后,如果我们利用 async / await,我们可以如下组合 action:
假设 getData() 和 getOtherData() 返回的是 Promise
actions: {
async actionA ({ commit }) {
commit('gotData', await getactionAData())
},
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // 等待 actionA 完成之后在支执行另一个异步的actionB
commit('gotOtherData', await getactionBData())
}
}