状态(数据)管理
由于多个状态分散的跨越在许多组件和交互间各个角落,大型应用复杂度也经常逐渐增长。为了解决这个问题,Vue 提供 vuex:
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
vuex基本介绍
每一个 Vuex 应用的核心就是 store(仓库)。"store" 基本上就是一个容器,它包含着你的应用中大部分的状态(state)
1.Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
2.你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交(commit) mutations。
核心概念
Store(最基本的概念)
State (数据)
Getters
Mutations
Actions
Modules
store
安装 Vuex 之后,让我们来创建一个 store
var store=new Vuex.Store({
state:{
count:0
},
mutations:{
jia(state){
state.count++;
},
jian(state){
state.count--;
},
}
});
通过 store.state 来获取状态对象,以及通过 store.commit 方法触发状态变更:
<input type="button" value="+" @click="$store.commit('jian')"/>
store.commit("jian");
console.log(store.state.count);
state
单一状态树
Vuex 使用 单一状态树 —— 是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个『唯一数据源(SSOT)』而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
在 Vue 组件中获得 Vuex 状态
由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态:
computed:{
count(){
return this.$store.state.count;
},
num1(){
return this.$store.state.num1;
}
},
每当 store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。Vuex 通过 store 选项,提供了一种机制将状态从根组件『注入』到每一个子组件中(需调用 Vue.use(Vuex)):
computed:Vuex.mapState({
count:state=>state.count,
num1:state=>state.num1,
}),
mapState 辅助函数
当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,
// 在单独构建的版本中辅助函数为 Vuex.mapState
computed:Vuex.mapState({
// 箭头函数可使代码更简练
count: state => state.count,
// 传字符串参数 'count' 等同于 `state => state.count`
countAlias: 'count',
// 为了能够使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
}
})
当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。
computed:Vuex.mapState(['count','num1']),
对象展开运算符
我们将它与局部计算属性混合使用时,我们需要使用一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给 computed 属性。
computed: {
...Vuex.mapState(['count','num1']),
localComputed () { /* ... */ },
// 使用对象展开运算符将此对象混入到外部对象中
})
}
组件仍然保有局部状态
getters
Vuex 允许我们在 store 中定义『getters』(可以认为是 store 的计算属性)。就像计算属性一样,getters的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
Getters 接受 state 作为其第一个参数,Getters 会暴露为 store.getters 对象:
getters:{
he(state){
return state.count+state.num1+state.num2+getters.jia5;
},
}
Getters 也可以接受其他 getters 作为第二个参数:
getters:{
he(state,getters){
return state.count+state.num1+state.num2+getters.jia5;
},
jia5(state){
return state.count+5
}
}
mapGetters 辅助函数
mapGetters 辅助函数仅仅是将 store 中的 getters 映射到局部计算属性:
computed:{
...Vuex.mapState(['count','num1','num2']),
...Vuex.mapGetters(['he']),
},
template:"<div>{{count}}-{{num1}}-{{num2}}={{he}}</div>"
mutations
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutations 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:
store.commit('increment')
提交载荷(Payload)
你可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload):
mutations:{
jia(state,arg){
state.count+=arg.n;
},
jian(state,arg){
state.count-=arg.n;
},
},
提交 mutation 的另一种方式是直接使用包含 type 属性的对象:
this.$store.commit({type='jia',n:3})
actions
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
actions:{
jia(commit){
commit({type:"jia",n:3});
}
},
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。