Vuex介绍
每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:
-
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
-
你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
git下载Vuex命令
$ cnpm install vuex --save
State
Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
Mutation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
Getters
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
Action
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
Module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
如果希望你的模块具有更高的封装度和复用性,你可以通过添加的namespaced:true方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名
仓库代码块
const store = new Vuex.Store({
state:{
num:1,
count:0,
msg:'',
list:[{type:1,name:'a'},{type:2,name:'b'},{type:3,name:'c'}],
type:'store'
},
mutations:{
setMsg(state,msg){
state.msg = msg
},
setNum(state,num){
state.num *= num
},
add(state,n){
setTimeout(() => {
state.count += n
}, 1000);
},
type(state){
console.log(state.type)
}
},
getters:{
myList(state,getters){
return state.list.filter(item=>item.type==1)
}
},
actions:{
addAsync({ commit,dispatch },n){
setTimeout(()=>{
commit('add',n)
},1000)
dispatch('show',2)
},
show({commit},n){
commit('setNum',n)
},
},
modules:{
map:{
namespaced:true,
state:{
type:'map'
},
mutations:{
type(state){
console.log(state.type)
}
},
getters:{
myList(state,getters){
console.log(arguments)
}
},
},
news:{
namespaced:true,
state:{
type:'news'
},
mutations:{
type(state){
console.log(state.type)
}
},
getters:{
myList(state,getters){
console.log(arguments)
}
},
}
}
})
调用含命名空间的模块的mutations或actions里面的方法的话 ( 以模块map为例)
//..
methods{
fn(){
this.$store.commit('map/type')
}
}
//或者
methods{
...mapMutations('map',['type'])
}
html部分
<div id="app">
<h2>输入值:{{msg}}</h2>
<div class="wrap">
<input type="text" :value="msg" @input="e => setMsg(e.target.value)"/>
<div class="add-box">{{count}}</div>
<div class="add-box">{{num}}</div>
<button @click="add(2)">add</button>
<button @click="addAsync(3)">actions</button>
<button @click="type">type</button>
<ul>
<li v-for="item in myList">{{item.name}}</li>
</ul>
<div>{{val}}</div>
</div>
</div>
辅助函数mapState
当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用mapState辅助函数帮助我们生成计算属性,让你少按几次键
//...
computed: {
...mapState({
count: state => state.count,
msg: state => state.msg,
num: state => state.num,
list: state => state.list,
val: state => state.map.type
})
}
辅助函数mapMutations
当触发一个类型为setMsg或者add的 mutation 时,你可以在组件中使用this.$store.commit('xxx')提交 mutation,或者使用mapMutations辅助函数将组件中的 methods 映射为store.commit调用
//...
methods:{
...mapMutations({
add:'add',
setMsg:'setMsg',
setnum: "setnum",
type: "type"
})
}
辅助函数mapState
辅助函数mapState,为组件创建计算属性以返回 Vuex store 中的状态
//...
computed: {
...mapState({
count: state => state.count,
msg: state => state.msg,
num: state => state.num,
list: state => state.list,
val: state => state.map.type
}),
},
辅助函数mapGetters
mapGetters辅助函数仅仅是将 store 中的 getter 映射到局部计算属性
//...
computed:{
...mapGetters({
myList:'myList'
})
}
辅助函数mapActions
你在组件中使用this.$store.dispatch('xxx') 分发 action,或者使用 mapActions
辅助函数将组件的 methods 映射为store.dispatch 调用
//...
methods: {
...mapActions({
addAsync: "addAsync"
})
}