背景:vuex store的进阶版 适用于大型复杂的单页应用
用途:数据管理
state 类似于 data
存储全局状态值,当改变值会触发dom更新, 使用时挂载在子组件的computed计算属性上(这样的目的是为了实时更新)
mapState
getters
getters 可以返回一个值(属性),也可返回一个方法函数
访问方法时 每次进行调用 不会缓存结果
访问属性时 作为vue响应式系统的一部分缓存起来
mapGetters --辅助函数
将store中的getter映射到局部计算属性,即 定义getter后 在总的vuex去注入这个getter 从而在全局进行使用
mutations
用于更改store中的状态值 包含一个事件类型和一个回调函数 不支持异步
mutations: {
increment (state, n) {
state.count += n
}
}
store.commit('increment', 10)
// 以对象形式传参
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
// amount相当于传入参数
store.commit('increment', {
amount: 10
})
actions
类似于mutations 支持异步 通过 store.dispatch 触发
actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
// 两种形式分发调用
store.dispatch('incrementAsync', {
amount: 10
})
store.dispatch({
type: 'incrementAsync',
amount: 10
})
mapActions
在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store)
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
}
actions 异步🌰
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
// 普通调用形式
store.dispatch('actionA').then(() => {
// ...
})
// 在别的action中调用
actions: {
// ...
actionB ({ dispatch, commit }) {
return dispatch('actionA').then(() => {
commit('someOtherMutation')
})
}
}
// async await
actions: {
async actionA ({ commit }) {
commit('gotData', await getData())
},
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // 等待 actionA 完成
commit('gotOtherData', await getOtherData())
}
} // 假设 getData() 和 getOtherData() 返回的是 Promise
modules
作用:将store分割成模块,每个模块拥有自己的 state、mutation、action、getter
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
const moduleA = {
state: () => ({
count: 0
}),
mutations: {
increment (state) {
// 这里的 `state` 对象是模块的局部状态
state.count++
}
},
getters: {
doubleCount (state) {
return state.count * 2
}
}
}
const moduleA = {
state: () => ({
count: 0
}),
mutations: {
increment (state) {
// 这里的 `state` 对象是模块的局部状态
state.count++
}
},
getters: {
doubleCount (state) {
return state.count * 2
}
},
actions: {
incrementIfOddOnRootSum ({ state, commit, rootState }) {
if ((state.count + rootState.count) % 2 === 1) {
commit('increment')
}
}
},
getters: {
sumWithRootCount (state, getters, rootState) {
return state.count + rootState.count
}
},
}
还有模块命名 模块继承 和更多复杂用法 详见:
https://vuex.vuejs.org/zh/gui...
总结
1.应用层级的状态应该集中到单个 store 对象中。
2.提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
3.异步逻辑都应该封装到 action 里面。
如果 store 文件太大,需将 action、mutation 和 getter 分割到单独的文件
项目架构
├── index.html
├── main.js
├── api
│ └── ... # 抽取出API请求
├── components
│ ├── App.vue
│ └── ...
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── cart.js # 购物车模块
└── products.js # 产品模块
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。