前言在之前的项目中,或多或少都有一些组件需要通信的地方,由于种种原因,eventbus的成本比vuex高,所以我技术选型选择了vuex,但是不知道为什么,团队里的一些新人一听到vuex就开始退缩了,因为vuex难吗?真的很难吗?今天我们就用3个简单的步骤来证明,vuex到底有多简单。纯属个人经验,难免有不正确的地方。如果你发现了什么,请指正我!这是新手入门教程,入门教程,入门教程。零步创建一个新的vue项目并安装Vuex,这里就不过多介绍了,如果你能点进去,你默认就有这些技能了^_^第一步是创建一个任意名字的.js文件和地点。按照惯例,建议在/src/store目录下(如果没有,可以自己新建一个)文件位置/src/store/index.js//importvueandvueximportVuefrom'vue'importVuexfrom'vuex'//这里需要用到,固定写法,记住Vue.use(Vuex)//直接导出一个Store实例exportdefaultnewVuex.Store({//类似vue的数据状态:{name:'oldName'},//类似于vue的mothods(同步方法)mutations:{updateName(state){state.name='newName'}}})代码看起来有点多,但是是不是很眼熟?和普通的vue没什么区别。这一步其实就是创建一个新的store,只是我们还没有在项目中使用过。第二步,在入口文件中引入上述文件,稍微改变一下传给newVue()的参数。换行后有注释文件位置/src/main.js(vue-cli自动生成的入口,如果可以使用脚手架,那我就不用解释了)importVuefrom'vue'importAppfrom'./App'importvuexStorefrom'./store'//添加新的Vue({el:'#app',store:vuexStore//新增组件:{App},template:''})Tip:importstorefrom'./store'后的地址就是我们上面创建的文件所在的位置(/src/store/index.html)js),因为我这里是index.js,所以可以省略。第三步和上面两步,其实vuex的基本配置已经完成,接下来就是使用文件位置/src/main.js(也是vue-cli生成的app.vue,这里为了方便为了演示,我删除了冗余代码){{getName}}
这是一个很普通的vue文件,不同的是我们需要使用computed属性来获取store中的“数据”,如果我们想改变数据,我们不再使用this.xxx=Changexxxtothis.$store。commit('updateName')综上所述,你可能会想,上面的例子这样做有什么意义,为什么不直接使用vue的数据和方法呢?上面的例子只是为了简单说明如何使用vuex,所以简化了一些流程之后,想象一下如果你有这样一个页面:一共嵌套了10层组件(也就是子组件里面有子子组件)sub-components,sub-sub-components下还有sub-sub-sub-components,以此类推10层)然后当最后一层组件中的一条数据发生变化时,我们要通知第一个层组件,我们只需要在底层组件使用this.$store.commit(),然后在最外层组件使用computed属性获取对应的值即可。它可以实时更新。不需要一层一层往上走$emit。结果原来是想在最后展开getter、action+dispatch、模块化等等,但是为了对得起这个称号,不得不放在下一篇:vuex其实超级简单。在这3个步骤之后,还有3个步骤。Vuex其实超级简单。在这3个步骤之后,还有3个步骤。之前的vuex其实超级简单。只需要3个步骤就可以简单介绍一下vuex的3个步骤。不过为了初学者容易消化,我删减了很多内容。如果你还没有看过上一篇文章,请先戳链接阅读再回来,否则你会觉得这篇文章很乱。纯属个人经验,难免有不准确之处。如有发现,欢迎指正!还是一样,这篇文章是针对初学者的。1.Getter我们先回忆一下上篇文章的代码。computed:{getName(){returnthis.$store.state.name}}这里,假设现在的逻辑已经改变,我们最终会根据this.$store.state计算出预期的数据(getName)。姓名。正好这个getName用到的地方比较多,所以我们要复制几份。Vuex为我们提供了一个getter,请看代码(文件位置/src/store/index.js)importVuefrom'vue'importVuexfrom'vuex'Vue.use(Vuex)exportdefaultnewVuex.Store({//类似vue的datastate:{name:'oldName'},//Computedlikevue--------------下面5行添加getters:{getReverseName:state=>{returnstate.name.split('').reverse().join('')}},//类似于vue中的方法(同步方法)mutations:{updateName(state){state.name='newName'}}})然后我们可以使用文件位置/src/main.js计算如下:{getName(){returnthis.$store.getters.getReverseName}}其实getter不仅起到了封装的作用,它还像Vue的computed属性一样缓存了结果数据,只有在依赖发生变化时才会重新计算。二、actions和$dispatch注意事项你一定注意到了,我之前的代码中mutationsheader的注释类似于vue中的mothods(同步方法)。为什么我要注意它是methods之后的同步方法?Mutationcanonlybeasynchronousfunction,onlyasynchronousfunction,它只能是同步函数!!请看vuex的解释:现在假设我们正在调试一个app,在devtool中观察mutationlog。每一个变化都被记录下来,devtools需要捕捉前一个状态和下一个状态的快照。然而,上面示例中变异中异步函数中的回调使得这成为不可能:因为当变异触发时回调函数尚未被调用,devtools不知道回调函数何时被实际调用——本质上任何状态变化在回调函数是不可追踪的。那么如果我们要触发一个异步操作呢?答案是:action+$dispatch,我们继续修改store/index.js下的代码文件位置/src/store/index.jsimportVuefrom'vue'importVuexfrom'vuex'Vue.use(Vuex)exportdefaultnewVuex.Store({//类似Vue的数据状态:{name:'oldName'},//类似Vue的计算getter:{getReverseName:state=>{returnstate.name.split('').reverse().join('')}},//类似于vue中的mothods(同步方法)mutations:{updateName(state){state.name='newName'}},//类似于vue中的mothods(异步方法)--------下面7个动作添加新的动作:{updateNameAsync({commit}){setTimeout(()=>{commit('updateName')},1000)}}})然后我们可以使用方法在我们的vue页面中是这样的:{rename(){this.$store.dispatch('updateNameAsync')}}3.模块模块化当项目越来越大的时候,单一的store文件肯定不是我们想要的,所以有模块化。假设src/store目录下有两个文件moduleA.jsexportdefault{state:{...},getters:{...},mutations:{...},actions:{...}}moduleB。jsexport默认值{状态:{...},getters:{...},mutations:{...},actions:{...}}然后我们可以改变index.js来importmoduleAfrom'./moduleA'importmoduleBfrom'./moduleB'exportdefaultnewVuex.Store({modules:{moduleA,moduleB}})这样我们就可以方便的把一个store拆分成多个。4.总结一下action的参数是storeobjects,getters和mutations的参数是state。动作和突变也可以传递第二个参数。详见vuex官方文档getters/mutations/actions都有对应的map,如:mapGetters。详见vuex官方文档模块。如果怕命名冲突的话,可以使用命名空间。具体可以看vuex的官方文档。实际上,vuex与vue非常相似。它有数据(状态)、方法(突变、动作)、计算(getters),并且可以模块化。