最近一直在自学vuex,官方文档刚开始看不懂,网上又看了很多资料,但是却越看越迷糊。自己稍微有了一点感悟以后,把它写下来,一方面为了梳理,另一方面可以分享出来供大家参考。
比如我们有一个表单组件,表单组件又包含了几个子组件,当子组件的数据和父组件的数据或者各个子组件数据之间发生交互的时候,它们之间的通信就会变得很麻烦。
在src目录下面创建一个vuex模块,然后在下面创建store.js
store.js如下:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state:{ count:1 } });然后在main.js里面引入并注册 如下
import Vue from 'vue' import App from './App' import router from './router' import store from './vuex/store' new Vue({ el: '#app', router, store, components: { App }, template: '<App/>' })我们可以在官方文档下面看到store对象下面主要有1.state 2.getter 3.mutation 4.action 5.module 五个模块。现在我们来通俗的解释一下这五个模块。
最简单的store.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state:{ count:1 } });在App.vue中
<template> <div id="app"> <h1>{{getCount}}</h1> <h1>{{count}}</h1> <h1>{{c}}</h1> </div> </template> <script> import { mapState } from 'vuex' export default { name:'App', computed:{ getCount:function() { return this.$store.state.count }, ...mapState([ 'count'//这种情况下count和store下的state中的count名字要一样 ]), ...mapState({ c:state => state.count }) } } </script>这样之后state中的count在我们项目中的任何组件下都可以访问到,其实在我的理解下就相当于我们js中的全局变量一样。 还有,我们看到computed下面有三种方式,其实这三种方式表达的意思是一模一样的,页面显示的结果也是一样。第二种和第三种方法用到了es6的语法,可以自己去看,不再解释。
getters 和 vue 中的 computed 类似 , 都是用来计算 state 然后生成新的数据 ( 状态 ) 的。 (无非就是利用state中的数据,然后经过我们的处理变成我们想要的数据) store.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state:{ count:1 }, getters: { getCount: state => { return state.count+1; } } });App.vue
<template> <div id="app"> <h1>{{count}}</h1> <h1>{{getCount}}</h1> </div> </template> <script> import { mapState } from 'vuex' import { mapGetters } from 'vuex' export default { name:'App', computed:{ count(){ return this.$store.getters.getCount }, ...mapGetters([ 'getCount' ]) } }我们已经有了“全局变量”state下的count,和能处理count的getter,那么当我们想要改变count的时候,mutation就派上用场了。 官方的解释:
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数(handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
store.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state:{ count:1 }, mutations: { increment (state,payload){ state.count += payload.amount; } } });App.vue
<template> <div id="app"> <h1 @click="increment">{{count}}</h1> <h1 @click="dispatch">{{count}}</h1> </div> </template> <script> import { mapMutations } from 'vuex' import { mapState } from 'vuex' export default { name: 'App', computed:{ ...mapState([ 'count' ]), }, methods:{ ...mapMutations([ 'increment' ]), dispatch: function() { this.$store.commit('increment') } } } </script>需要主要的是mutation中的方法是不可以进行异步操作的,想要异步操作,我们需要引出actions
多个 state 的操作 , 使用 mutations 会来触发会比较好维护 , 那么需要执行多个 mutations 就需要用 action 了
store.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state:{ count:16 }, getters: { getCount: state => { return state.count+578; } }, mutations: { increment (state,payload){ state.count += payload.amount; } }, actions: { increment (context) { context.commit('increment') } } });App.vue
<template> <div id="app"> <<h1 @click="increment">{{count}}</h1> <h1 @click="add">{{count}}</h1> </div> </template> <script> import { mapActions} from 'vuex' import { mapState } from 'vuex' export default { name: 'App', computed:{ ...mapState([ 'count' ]), }, methods:{ ...mapActions([ 'increment'// 将 `this.increment()` 映射为 `this.$store.dispatch('increment')` ]) ...mapActions({ add:'increment' }), } } </script>module类似于将store模块化,变成一个一个的小模块
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
store.js
import Vue from 'vue'; import Vuex from 'vuex'; import index from './store/index'; Vue.use(Vuex); export default new Vuex.Store({ modules: { index: index }, });index.js
export default { state:{ count:16 }, getters: { getCount: state => { return state.count+578; } }, mutations: { increment (state,payload){ state.count += payload.amount; } }, actions: { increment (context) { context.commit('increment') } } }大体上就是这么回事,看懂这些,再去看官方的文档就会觉得很简单,不要被其他一些文章吓到。
