这是我参与「第四届青训营 」笔记创作活动的第9天
VueX
感谢官方文档,本文示例以及部分章节为原文内容。
本文主要在学习了状态管理中Redux 和Vuex 之后,对Vuex 进行复习归纳。
VueX与Redux 很多地方是相似的,比如有一个store ,有state,mutation ,但是action 的概念不太一样,会在稍后进行解释。
因此,本文更确切的说是Vuex与Redux的对比。
最简单的示例
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
//获取数据
store.state
//进行状态更新
store.commit('increment')
核心概念
State
单一状态树
Vuex 使用单一状态树,即一个对象就包含了整个应用的状态,是作为唯一数据源的存在。而这个状态树,即是store 的实例,并且这个单一状态树也能够让开发者在调试过程中随时取得整个应用的快照。
mapState
使用mapState 函数使得代码变得简洁。
否则如果你在一个组件内获取多个状态的话,得把每个状态写一个计算属性。但是用了mapState 函数,就会很简洁。
⚠️ :在Redux 中,可以使用Selector 来减少重复获取相同的值所带来的性能消耗。
//有三种传参方式
computed: mapState({
// 箭头函数可使代码更简练
count: state => state.count,
// 传字符串参数 'count' 等同于 `state => state.count`
countAlias: 'count',
// 为了能够使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
}
})
//如果计算属性名称与要获取的state的名称一样
computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])
如果这样的话,就不能再设置别的计算属性了,因此可以使用对象展开运算符 将其他计算属性 与 获取store状态的属性一起用。
computed: {
localComputed () { /* ... */ },
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
// ...
})
}
Getter
类似于Redux 中的 Reducer
直接访问state中的数据,获得的就是原数据,而要想获得的返回值是对原数据进行一定操作的,比如原数据+1之类,那么就需要用到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)
}
}
})
也接受其他getter 作为第二个参数
getters: {
// ...
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
属性访问
可以直接通过属性访问,例如
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
通过方法访问
通过让getter 返回一个函数,来实现给getter 传递参数。如果你需要对store 里的数组查询,这会很有用
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
//访问
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
mapGetters
同mapState
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
//也可以这么写,
//把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
// ...
])
}
}
Mutations
对应Redux中的dispatch
每个mutation 有一个字符串类型的type 和一个回调函数。
回调函数就是我们对状态进行更改的地方
参数
这个回调函数会接受state 作为第一个参数
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
//调用
store.commit('increment');
回调函数可以接受额外的参数,称作载荷
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
//调用
store.commit('increment', {
amount: 10
})
对象风格提交方式
可以把commit 的参数写作一个对象,把mutations名作为type字段。 而mutations 函数不需要做任何变化。
store.commit({
type: 'increment',
amount: 10
})