共计 3415 个字符,预计需要花费 9 分钟才能阅读完成。
最近比较闲,抽时间过了一遍 vuex 的文档。同时写了官网上购物车的那个小 demo。下面来总结一下一些 vuex 的一些知识点
一.vuex 是什么?
官方文档上写:vuex 是一个专为 vue.js 应用程序开发的状态管理模式。这个状态自管理应用包括以下几个部分:
state, 驱动应用的数据源;
view, 以声明方式将 state 映射到视图;
actions, 响应在 view 上的用户输入导致的状态变化。
二.vuex 的核心
vuex 应用的核心就是 store(仓库)。”store” 基本上就是一个容器, 它包含着你的应用中大部分的状态(state)。
vuex 的状态是响应式的。即:若 store 中 state 发生改变,组件会随之更新。
你不能直接修改 state,而是使用 commit 显示地提交 mutation。
三.State
在 vue 组件中获取状态
// 创建一个 Counter 组件
const Counter = {
template: `<div>{{count}}</div>`,
computed: {
count () {
return store.state.count
}
}
}
使用 mapState 辅助函数在一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些复杂。为了解决这个问题,可以使用 mapState 辅助函数
// 在单独构建的版本中辅助函数为 Vuex.mapState
import {mapState} from ‘vuex’
export default {
computed: mapState({
count: state => state.count,
// 传入字符串 ’count’ 等同于 ’state => state.count’
countAlias: ‘count’,
// 使用模块并且对应模块名称为 cart 时, 获取 cart 里面对应的 count 属性
count: state => state.cart.count
})
}
当计算属性的名称与 state 子节点名称相同时, 可以给 mapState 传入一个字符串数组
computed: mapState([
‘count’
])
对象展开运算符 …mapState
computed: {
localComputed() {
…mapState({
})
}
}
四.Getter
从 store 中的 state 派生出一些状态。可以理解为 store 的计算属性。当 getter 所依赖的值发生改变时,getter 的值会随之改变。
import {mapGetters} from ‘vuex’
export default {
// …
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
…mapGetters([
‘doneTodosCount’,
‘anotherGetter’,
// …
])
}
}
如果你想将一个 getter 属性另取一个名字,使用对象形式:
mapGetters({
// 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
doneCount: ‘doneTodosCount’
})
模块化状态下,getter 取值
// 模块为 cart
computed: {
…mapGetters(‘cart’, {
doneCount: ‘doneTodosCount’
})
}
五.Mutation
更改 vuex 的 store 中的状态的唯一办法是提交 mutation 注意:
mutation 必须是同步函数, 异步需要放在 aciton 中
const store = new Vuex.store({
state: {
count:1
},
mutations: {
increment (state) {
state.count++
}
}
})
store.commit(‘increment’)
提交载荷(Payload) 你可以向 store.commit 传入额外的参数, 即 mutaition 的荷载(payload)
mutations: {
increment(state, n) {
state.count += n
}
}
store.commit(‘increment’, 10)
在组件中提交 mutation
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 store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit(‘increment’)
}
// 或者也可以用 es2015 的解构赋值写成下面这种形式
increment({commit}) {
}
}
})
分发 ActionAction 通过 store.dispatch 方法触发
store.dispatch(‘increment’)
在组件中分发 Action
import {mapActions} from ‘vuex’
export default {
// …
methods: {
…mapActions([
‘increment’, // 将 this.increment()映射为 this.$store.dispatch(‘increment’)
])
…mapActions([
add: ‘increment’ // 将 `this.add()` 映射为 `this.$store.dispatch(‘increment’)`
])
}
}
七.Module
Vuex 允许我们将 store 分割成模块。
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 的状态
默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的。如果你希望你的模块具有更高的封装度和复用度,你可以通过添加 namespaced:true 的方式使其成为带命名空间的模块。在模块被注册后,它所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
const store = new Vuex.Store({
modules: {
account: {
namespaced: true,
state: {},
getters: {
isAdimin() {…} // getters[‘account/isAdmin’]
}
}
}
})
对于内部模块, 如果你希望获取全局的 state 和 getter, 可以通过 rootState、rootGetter 获取到 若需要在全局命名空间内分发 action 或者提交 mutation, 将 {root: true} 作为第三个参数传给 dispatch 或者 commit 即可
// 在另外一个模块获取 cart 模块
rootState.cart.all
dispatch(‘someOtherAction’, null, { root: true}) // -> ‘someOtherAction’
commit(‘someMutation’, null, { root: true}) // -> ‘someMutation’