简单学一下Vuex
众所周知在vue中,组件之间传递数据需要一步一步接着传递,这样写起来很麻烦,也会使代码晦涩难懂。因此,vuex诞生了!
vuex is what?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
说白了,vuex就是一个仓库,用来存储状态(也就是数据),这些状态可以在不同组件中很方便地获取到。
vuex的使用
目录
先来看vuex的目录基本结构。先建一个store文件夹,文件夹下有两个主要的文件(夹),一个是index.js,一个是modules文件夹。

-
index.js:vuex的入口,用于注册
module,常规的写法通常将store分成几个模块(module),再在入口文件里统一注册
-
modules:每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块
const moduleA = { state: () => ({ ... }), mutations: { ... }, actions: { ... }, getters: { ... } }
接下来对模块的各个方法进行详细介绍
状态(state)
state可以看做组件的data,用于存储状态对象
// 示例
const state = {
count:0
}
在Vue 组件中展示状态
// 示例:一个 Counter 组件
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return store.state.count // 这里
}
}
}
mapState 辅助函数
当一个组件需要获取多个状态的时候,我们一个一个写显得很不美观,这时候可以用mapState 辅助函数帮助我们生成计算属性,也显得b格比较高大上
import { mapState } from 'vuex'
export default { // 对象展开运算符
computed: {
...mapState([
// 映射 this.count 为 store.state.count
'count'
]),
otherComputed () { /* ... */ },
}
}
Getter
有时候我们并不是直接想要一个数据,比如需要对列表进行过滤并计数:
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length
}
}
在多个组件中复制这个函数不是很理想,这时候就可以用到getter
就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => { // Getter 接受 state 作为其第一个参数
return state.todos.filter(todo => todo.done)
}
}
})
mapGetters 辅助函数
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
Mutation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
const state = {
count:0
}
const mutations = {
increment (state) {
// 变更状态
state.count++
}
SET_COUNT: (state, payload) => {
// 提交载荷(Payload)
state.count = payload
}
}
// other.vue
this.$store.commit('increment')
this.$store.commit('SET_COUNT', 10)
一条重要的原则就是要记住Mutation 必须是同步函数
mapMutations 辅助函数
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
// `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
}
Action
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
const state = {
count:0
}
const mutations = {
increment (state) {
// 变更状态
state.count++
}
}
const actions = {
incrementAsync ({ commit }) { // 模拟异步操作
setTimeout(() => {
commit('increment')
}, 1000)
}
}
// other.vue
this.$store.dispatch('incrementAsync')
购物车示例,涉及到调用异步 API 和分发多重 mutation:
actions: {
checkout ({ commit, state }, products) {
// 把当前购物车的物品备份起来
const savedCartItems = [...state.cart.added]
// 发出结账请求,然后乐观地清空购物车
commit(types.CHECKOUT_REQUEST)
// 购物 API 接受一个成功回调和一个失败回调
shop.buyProducts(
products,
// 成功操作
() => commit(types.CHECKOUT_SUCCESS),
// 失败操作
() => commit(types.CHECKOUT_FAILURE, savedCartItems)
)
}
}
mapActions 辅助函数
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // `this.increment()` / 'this.increment(amount)'
]),
}
}
Action 通常是异步的,那么如何知道 action 什么时候结束呢?