vuex的东西比较碎,还是要慢慢理解。
一、vuex介绍
对 vue 应用中多个组件的共享状态进行集中式的管理(读/写)。
1.1 组成部分
- state,核心,保存应用程序状态的容器,驱动应用的数据源;
- view,以声明方式将 state 映射到视图;
- actions,响应在 view 上的用户输入导致的状态变化。
作用:解决多个视图依赖于同一状态, 来自不同视图的行为需要变更同一状态
二、核心概念
2.1 state
存储状态(变量),包含了全部的应用层级状态
const store = new Vuex.Store({
state:{
//存放的键值对就是所要管理的状态
count:0
}
})
通过计算属性获取store中状态
computed:{
count(){
return this.$store.state.count;
}
}
mapState函数
用于生成计算属性
使用
// 引入
import { mapState } from 'vuex'
computed:mapState({
count: 'count',
msg: 'message'
})
注:如果计算属性要使用组件中的数据属性,那么就需要使用普通函数的方式
写法二:
计算属性的名字与store中状态属性的名字相同,则可以进一步简化,写法如下:
computed:mapState([
'count',
'message'
])
写法三:
混入本地计算属性
computed:{
localComputed (){return '本地计算属性' } ,
...mapState([
'count', 'message'
])
}
2.2 mutations
是操作state数据的方法的集合,更改 Vuex 的 store 中的状态的唯一方法是提交mutation。mutation非常类似于事件。
const store = new Vuex.Store({
state:{
//存放的键值对就是所要管理的状态
count:0
},
// 一个方法就是一个 mutation
// mutation 只能包含更新 state 的同步代码, 也不会有逻辑
mutations:{
// state:当前VueX对象中的state
// data:该方法在被调用时传递的参数
increment(state,data){
state.count+=data
}
}
})
提交mutation
this.$store.commit('increment',1)
使用包含type属性的对象提交
this.$store.commit(
{
type:'increment',
amount:10
})
mapMutations函数
可以将组件中的方法映射为store.commit调用
写法1:
methods:mapMutations(
['increment','decrement']
),
写法2:组件中有自己的方法,可通过es6展开运算符,提取mapMutations函数返回的对象属性,复制到methods选项中
methods:{
...mapMutations(
['increment','decrement']
),
test(){}
}
2.3 getter
可理解为store的计算属性,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
定义:
const store = new Vuex.Store({
....
getters:{
userName:state =>state.firstName+state.lastName
}
})
直接使用
<h1>姓名:{{this.$store.getters.userName}}</h1>
mapGetters
获取getters计算属性
computed:{
...mapGetters(['userName'])
}
2.4 action
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,
调用 context.commit 提交一个 mutation
或者通过 context.state 和 context.getters 来获取 state 和 getters
actions:{
increment(context){
context.commit('increment',1)
}
}
触发
<button @click="$store.dispatch('increment',3)">+3</button>
与mutation最主要的区别就是action中可以包含异步操作
actions:{
increment (context,data) {
setTimeout(() => {
context.commit('increment',data)
}, 1000)
}
}
mapActions
将组件的方法映射为store.dispatch调用
methods:{
...mapActions(['increment'])
}
2.5 数据流向图
官方图
补充图
2.6 module
Vuex使用单一状态树,应用程序的所有状态都包含在一个大的对象中,当应用变得复杂时,store对象会变得非常臃肿。将store划分为多个模块,可解决此问题,每个模块都可以包含自己的state、mutations、actions、getters
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,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState
actions: {
incrementIfOddOnRootSum ({ state, commit, rootState }) {
console.log("局部aciton被调用")
console.log("state.count:"+state.count)
console.log("rootState.count:"+rootState.count)
commit('increment')
}
}
对于模块内部的 getter,根节点状态会作为第三个参数暴露出来
getters: {
sumWithRootCount (state, getters, rootState) {
return state.count + rootState.count
}
},
注:模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。
命名空间
通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
export const moduleA = {
namespaced: true,
....
}
组件调用
methods:{
...mapActions('a',['incrementIfOddOnRootSum']),
/* add(){
this.$store.dispatch('a/incrementIfOddOnRootSum')
}*/
}
内部调用
actions: {
someOtherAction(context){
console.log("局部acition被调用")
},
incrementIfOddOnRootSum (context) {
console.log("局部getters:"+context.getters.someGetter)// -> 'moduleA/someGetter'
console.log("全局getters:"+context.rootGetters.someGetter)// -> 'someGetter'
context.dispatch('someOtherAction') // -> 'moduleA/someOtherAction'
context.dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'
context.commit('increment') // -> 'moduleA/someMutation'
context.commit('increment', null, { root: true }) // -> 'someMutation'
}
}
computed:{
....
sumCount (){
return this.$store.getters['moduleA/someGetter']
}
},