官方说明:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 global event bus 就足够您所需了。但是,如果您需要构建是一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
显然现在不是讨论用不用vuex的时候,直接进入主题。
在vue.js组件传值中介绍了父子组件之间的传值,使用vuex可以解决一般性的组件之间数据共享,即没有关联的两个组件之间也可以共享组件。
1.全局注册vuex
在新建src/store/index.js(个人文件结构习惯,仅供从参考),代码:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
//...
})
现在有vuex实例,那么如何去使用它呢?
在vue的入口main.js中全局注册我们刚刚新建的vuex,main.js中添加代码:
import store from './store'
new Vue({
// ...
store
})
这样在所有的组件中都可以通过this.$store访问vuex实例。
2.state
vuex中所有的状态都在state中,有点想vue中的data。修改上面的示例,在修改src/store/index.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:0,
todoList:[
{id: 1,text: 'homework',finish:true},
{id: 1,text: 'run',finish:false}
]
}
})
那么各个组件可以通过this.$store.state.count访问vuex实例中的count,如在组件vueA.vue中:
<p>init count = {{count}}p>
computed: {
count () {
return this.$store.state.count
}
}
这样只要vuex中的count有修改,vueA中的count也会修改。
3.getter
有时候我们需要从 store 中的 state 中派生出一些状态,如
在实际应用中可以会有一些组合状态,但是在各个组件中,不能在各个组件中通过运算获取这些组件状态,因为这样可能导致各个组件之间状态不一致,并且维护起来不方便,对于这种组合状态,可以在vuex中统一运算,通过getter暴露给各个组件,保持组件的状态一致,也方便维护。
举一个简单的栗子:
对于上例中的todoList,vuex提供一个获取已经完成list的方法,即总是给出finish == true的todolist:
getters: {
doneList (state){
return state.todoList.filter(item => item.finish)
}
}
各个组件获取doneList :
computed: {
doneList () {
return this.$store.getters.doneList
}
}
这样组件只负责获取vuex中的状态,而状态的逻辑由vuex控制。
4.mutations
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
这句话的意思是组件可以通过this.$store.state.count访问vuex中的状态,但是这是只读的,不能通过简单的赋值改变vuex中的状态,这样做的好处在于无法简单改变vuex的状态,必须要显示的提交修改,便于掌握数据的流向。
假设我们现在需要使上例中的count加1,通过上面的说明,this.$store.state.count++是不会起作用的。
那么如何实现count加1?添加src/store/index.js代码:
mutations: {
addCount (state) {
state.count++
},
minCount (state) {
state.count--
}
}
在mutations中定义了addCount 和minCount ,通过代码看到分别实现了count加一和减一,在组件中调用方法如下:
<button @click="add()">+1button>
methods: {
add () {
this.$store.commit('addCount')
}
}
通过this.$store.commit(‘addCount’)调用vuex的mutations中的addCount。
如果希望传递其他的参数:
mutations: {
addCount (state,para) {
state.count++
}
}
this.$store.commit('addCount',para)
mutations中的方法第一个参数为state,传递过去的参数依次往后。
5.action
官方说明:action 类似于 mutation,不同在于:
Action 可以包含任意异步操作。
示例:
actions: {
addCount (context) {
setTimeout(() => {
context.commit('addCount')
},1000)
}
}
组件中访问:
this.$store.dispatch('addCount')
可以看到通过dispatch关键字访问action中的方法,而在action中需要改变vuex中的状态,仍然需要显示调用commit。
6.modules
为了解决臃肿问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter。
详情见官网https://vuex.vuejs.org/zh-cn/modules.html
7.map…
关键字state、getters、mutations、actions都有对应的map关键字,分别为mapState 、mapGetters 、mapMutations、mapActions
他们的主要作用是映射。
对于mapState、mapGetters 主要用于组件的computed中:
computed: {
localComputed () { /* ... */ },
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
// ...
})
}
主要作用是使代码更加简洁,对比两种写法:
count () {
return this.$store.state.count
}
...mapState ({
count:'count'
})
这样假如有大量的状态,使用mapState只需要做映射,而第一种写法每次都要return this.$store.state.count
其他的map系列都是同样的作用,不一一细讲。
代码地址:https://github.com/Demon-han/vuex-demo/