官网地址:https://vuex.vuejs.org/zh/guide/
每个【vuex】应用的核心 就是【store】(仓库)
【store】基本上就是一个容器,它包含着你的应用中大部分的【状态】(state)
Vuex 和单纯的全局对象的区别
- Vuex 的状态存储是响应式的。当Vue组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么对应的组件也会相应的得到高效更新。
- 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径,就是显式的【提交】(commit)mutation,这样使得我们可以方便的跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好的了解我们的应用。
简单的 store
// 如果在模块化的构建系统中,请确保在开头调用 Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count ++
}
}
})
// 触发状态变更
store.commit('increment')
// 读取状态
console.log(store.state.count)
Getter
可以认为是 store 的计算属性
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
// 传参
getTodoById: state => id => {
return state.todos.find(todo => todo.id === id)
}
// 调用
// store.getter.getTodoById(2)
}
})
辅助函数 mapGetters
mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部的计算属性
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开符,将 getter 混入到 computed 计算属性中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
// 如果想将 getter 属性另取一个名
...mapGetters({
// 把 this.doneCount 映射到 this.$store.getters.doneTodosCount
doneCount: 'doneTodosCount'
})
}
}
Mutation(必须是同步函数)
更改 Vuex 的 store 中的状态的唯一方法是提交(commit)mutation
调用:store.commit(‘increment’)
const store = new Vuex.Store({
state: {
count: 1
},
mutation: {
increment(state) {
// 变更状态
state.count ++
}
}
})
提交载荷(payload)
你可以向 store.commit 传入额外的参数,即 mutation 的载荷(payload)
Action
类似于 mutation,不同点在于:
- Action 提交的是 mutation,而不是直接变更状态
- Action 可以包含任意异步操作
const store = new Vuex.Store({
state: {
count: 0
},
mutation: {
increment (state) {
state.count ++
}
},
actions: {
increment({ commit, state }) {
commit('increment')
}
}
})
分发 Action
store.dispatch('increment')
// 以载荷方式分发
store.dispatch('increment', {
amount: 10
})
// 以对象方式分发
store.dispatch({
type: 'increment',
amount: 10
})
在组件中分发【…mapActions】
组合 Action
store.dispatch 可以处理被触发的 action 的处理函数返回的Promise,并且 store.dispatch 仍旧返回 Promise
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
分发 actionA
store.dispatch('actionA').then(() => {
// ...
})
在另一个 action 中也可以调用
actions: {
// ...
actionB ({ commit, dispatch }) {
return dispatch('ActionA').then(() => {
commit('someOtherMutation')
})
}
}
Module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象,使应用变得非常复杂,store对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块(从上到下进行同样方式的分割)
const moduleA = {
state: { count: 0 },
mutations: {
increment(state) {
// 这里 state 指模块的局部变量
state.count ++
}
},
actions: {
// rootState 为根节点状态
// state 为局部状态
incrementOther({ state, commit, rootState }) {
commit('increment')
}
},
getters: {
doubleCount (state) {
return state.count * 2
}
}
}
const moduleB = {
state: {...},
mutations: {...},
actions: {...}
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
input 双向绑定的计算属性
使用带有 setter 的双向绑定的计算属性
<input v-model="message">
// ...
computed: {
message: {
get () {
return this.$store.obj.message
},
set(value) {
this.$store.commit('updateMessage', value)
}
}
}