快速了解Vuex
Vuex快速学习
前情提要
本文旨在快速了解Vuex相关使用方法,同时也想通过记录博客的方式记录笔记。
Vuex是什么
Vuex是Vue官方提供的状态管理器,为多个组件共享状态时提供的解决方案。
vuex
Vuex例子
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
action: {
}
})
//调用
this.$store.commit('increment')
console.log(this.$store.state.count) // -> 1
要了解一个组件如何使用,先了解一下组件的核心概念吧。
Vuex核心概念
State
Vuex存储共享数据的对象
-
数据访问方式:
this.$store.state.属性名称 -
数据修改方式: 参见Mutation、Action
-
mapState辅助函数:当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余,那就需要使用mapState。-
使用方式1
//在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'
export default {
// ...
computed: mapState({
// 箭头函数可使代码更简练
count: state => state.count,
// 传字符串参数 'count' 等同于 `state => state.count`
countAlias: 'count',
// 为了能够使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}
//简写
computed: mapState([
// 映射 this.count 为 store.state.count
'count'
]) -
使用方式2
computed: {
localComputed () { /* ... */ },
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
// ...
})
}
-
Getter
提供共享的数据的计算属性,减少在组件内部写计算属性的冗余。
-
使用方式
//Getter 接受 state 作为其第一个参数
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)
}
}
})
//调用
this.$store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
//传参方式
//通过让 getter 返回一个函数,来实现给 getter 传参
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
//调用
this.$store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false } -
调用方式:
this.$store.getters.属性名称 -
mapGetters辅助函数:将 store 中的 getter 映射到局部计算属性-
使用方式
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
//起别名
...mapGetters({
// 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})
-
Mutation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
-
使用方式
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
},
increment (state, n) {
state.count += n
}
}
})
//调用方式1
this.$store.commit('increment')
//调用方式2 payload 传参
this.$store.commit('increment',10)
//调用方式3 对象风格的提交方式
this.$store.commit({
type: 'increment',
amount: 10
}) -
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')`
})
}
} -
遵守相关规范
- Mutation 必须是同步函数
Action
Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
注意:Action 提交 mutation ,mutation 修改store。
-
使用方式
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
},
increment (state, n) {
state.count += n
}
},
actions: {
increment (context) {
context.commit('increment')
},
//异步方式
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
})
//调用1
this.$store.dispatch('increment')
//调用2 payload 传参
this.$store.dispatch('increment',{
amount: 10
})
//调用3 对象风格的提交方式
store.dispatch({
type: 'incrementAsync',
amount: 10
})
//使用例子
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)
)
}
} -
组件内调用(分发)方式:
this.$store.dispatch('action方法名称') -
mapActions辅助函数: 类mapMutations,简化组件分发。-
使用方式
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')`
})
}
}
-
Module
Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 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 的状态 -
使用细节:使用模块化后
mutations、getters、actions参数暴露方式有所不同,具体请参照官方文档 -
命名空间:模块内部添加
namespaced属性为trueconst store = new Vuex.Store({
modules: {
account: {
namespaced: true,
// 模块内容(module assets)
state: () => ({ ... }), // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响
getters: {
isAdmin () { ... } // -> getters['account/isAdmin']
},
actions: {
login () { ... } // -> dispatch('account/login')
},
mutations: {
login () { ... } // -> commit('account/login')
},
// 嵌套模块
modules: {
// 继承父模块的命名空间
myPage: {
state: () => ({ ... }),
getters: {
profile () { ... } // -> getters['account/profile']
}
},
// 进一步嵌套命名空间
posts: {
namespaced: true,
state: () => ({ ... }),
getters: {
popular () { ... } // -> getters['account/posts/popular']
}
}
}
}
}
})
当你的才华还撑不起你的野心的时候,你就应该静下心来学习。当你的能力还驾驭不了你的目标的时候,你就应该沉下心来历练。

浙公网安备 33010602011771号