vuex—数据管理器
“vuex是用于Vue的状态管理模式,它采用集中式存储管理应用的所有组件的状态。”
vuex的应用核心就是仓库(store),管理的是状态,状态,就是共用的属性或者数据,vuex将共用的属性进行管理,vuex的特点,第一点状态存储是响应式的,第二点就是不能直接更改store的状态,改变store的状态的唯一途径就是显示的提交mutations
对于每一个应用来说,仅仅只含有一个store实例
安装方法:
npm install vuex –save
关于State
state:状态对象,共享值就可以叫做状态
首先必须先导入store.js
import Vue from ‘vue’
import Vuex from ‘vuex’Vue.use(Vuex);
store.js
的内容:
const store = new Vuex.Store({
state: {
num: 0
},
mutations: {
increment (num) {
state.num++
}
}
})
访问state的值的方法:
- 计算属性返回一个状态:Store.state.count
- 通过store选项
const app = new Vue({
el: '#app',
store, // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
components: { Counter },
template: `<div class="app"><counter></counter></div>`
})
在子组件下就可以访问到
this.$store.state.count
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
mapState
辅助函数
当一个组件要获取多个状态时候,将这些状态都声明为计算属性有些重复和冗余,通过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
}
})
}
当映射的计算属性的名称和state的子节点名称相同时,可以给mapState传递一个数组
computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])
关于Getters
当需要从state
中派生出一些状态,比如说对列表进行过滤并计数
首先的想法就是可以通过计算属性对这些进行获得,但是如果都通过计算属性获得,就会产生代码的冗余,vuex中可以允许定义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)
}
}
})
通过store.getters.doneTodos
进行使用,第二个参数可以是其它的getters
也可以借助mapGetters
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getters 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
扩展运算符...
,当既要通过计算属性取得state中的某个值,又要想调用getter中的过滤函数,而扩展运算符就是一个不错的选择
computed: {
//取得state中的某个值
...mapState(['count']),
//调用getter中的过滤函数
count() {
return this.$store.getters.doneTodos;
}
}
上面的也可以简写
import { mapGetters } from 'vuex'
computed: {
//取得state中的某个值
...mapState(['count']),
//调用getter中的过滤函数
...mapGetters({'doneTodos'})
}
Mutation
更改Vuex的store中的状态的唯一方法是提交,在组件中我们不能直接调用Mutations中的方法,只用通过commit
才可以,比如这样:
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
state.count++
}
}
})
调用方式:
store.commit('increment')
当然也可以这样,传递一个额外的参数
mutations: {
increment (state, n) {
state.count += n;
}
}
store.commit('increment', 10)
mutation
必须是同步函数,因为回掉中状态的改变是不可追踪的
上面的store.commit('increment')
在组件中书写也显得很麻烦
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment' // 映射 this.increment() 为 this.$store.commit('increment')
]),
...mapMutations({
add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')
})
}
}
也可以这样:
methods : mapMutations(['add', 'reduce'])
Action
Action类似于mutation,不同之处
- Action提交的是mutation,而不是直接变更状态
- Action可以包含任意异步操作
actions: {
addActions(context) {
context.commit('add', 100)
},
reduceAction({commit}) {
commit('reduce');
}
}
import {mapActions, mapMutations} from 'vuex'
methods: {
...mapMutations(['add', 'reduce']),
//this.$store.dispatch('addAction')
...mapActions(['addAction', 'reduceAction'])
}
体现异步:
actions: {
addActions(context) {
context.commit('add', 100);
setTimeout(() => {context.commit('reduce')}, 4000);
},
reduceAction({commit}) {
commit('reduce');
}
}
分发:
Action可以通过store.dispatch('increment')
在组件中可以使用上面的方式,也可以
methods: {
...mapActions([
'increment' // 映射 this.increment() 为 this.$store.dispatch('increment')
]),
...mapActions({
add: 'increment' // 映射 this.add() 为 this.$store.dispatch('increment')
})
}
模块组
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 的状态