从零开始学习Vuex
时间:2023-03-30 18:30:03
CSS
1.前言当我们的应用程序遇到多个组件共享状态时,多个组件将需要依赖相同的状态或者来自不同视图的行为需要更改相同的状态。以前的解决方案:在父组件中定义数据和操作数据的行为;b.将数据和操作数据的行为传递给需要的子组件(可能需要多级传递)传递参数的方式对于多层嵌套的组件来说会很繁琐,并且不能做兄弟组件之间的状态传递.在构建下面的页面时,你可能会对vue组件之间的通信感到崩溃,尤其是非父子组件之间的通信。这时候就应该使用vuex来轻松解决组件之间的通信问题。2、什么是VuexVuex是专门为Vue.js应用开发的状态管理模型。它使用集中存储来管理应用程序所有组件的状态,并使用相应的规则来确保状态以可预测的方式变化。这里的关键是集中存储管理。简而言之,集中管理(读/写)一个Vue应用程序中多个组件的共享状态。三、Vuex的原理是什么1、Vuex原理简介Vuex实现了一种单向的数据流,有一个State来全局存储数据。当一个组件想要改变State中的数据时,必须通过Mutation来完成,Mutation也提供了subscription的模式,供外部插件调用获取State数据的更新。但是,当所有的异步操作(常用调用后端接口异步获取更新数据)或者批量同步操作都需要action时,action不能直接修改state,还是需要mutation来修改state数据。最后根据State的变化渲染到view上。2.简单介绍一下流程中各个模块的主要功能:VueComponents:Vue组件。在HTML页面上,它负责接收用户操作等交互动作,并执行dispatch方法触发相应动作响应。dispatch:操作行为触发方法,是唯一可以执行action的方法。actions:动作处理模块,由组件中的$store.dispatch('actionname',data1)触发。然后commit()触发突变调用以间接更新状态。负责处理Vue组件接收到的所有交互。包含同步/异步操作,支持多个同名方法,按照注册顺序依次触发。向后台API请求的操作都在这个模块中执行,包括触发其他操作和提交突变。该模块提供对Promise的封装,支持action的链式触发。commit:状态改变提交操作方法。提交突变是执行突变的唯一方法。mutations:状态改变操作方法,由actions中的commit('mutationname')触发。是Vuex修改状态的唯一推荐方式。该方法只能进行同步操作,方法名只能全局唯一。运行过程中会暴露一些hook,用于状态监控等。state:页面状态管理容器对象。将数据对象的分散数据集中存储在Vue组件中,全局唯一统一状态管理。页面显示所需的数据就是从这个对象中读取的,利用Vue细粒度的数据响应机制进行高效的状态更新。getters:状态对象的读取方法。该模块未在图中单独列出,应包含在render中。VueComponents通过这个方法读取全局状态对象。4.什么时候使用Vuex虽然Vuex可以帮助我们管理共享状态,但是它也自带了更多的概念和框架。这需要在短期利益和长期利益之间进行权衡。如果你的应用程序足够简单,你最好不要使用Vuex,因为使用Vuex会很麻烦和多余。您只需要一个简单的全局事件总线。但是,如果你需要构建一个中大型的单页应用,你很可能会考虑如何在组件外部更好地管理状态,而Vuex将成为一个自然而然的选择。5.vuex安装(开发环境仅限vue-cli)首先需要安装vue-cli脚手架。对于大陆用户,建议将npm注册源设置为国内镜像(淘宝镜像),可以大大提高安装速度。npmconfigsetregistryhttps://[registry.npm.taobao.org](http://registry.npm.taobao.org/)npmconfiggetregistry//配置完成后可以验证是否成功npminstall-gcnpm--registry=[https://registry](https://registry/).npm.taobao.org//cnpm安装脚手架cnpminstall-gvue-clivueinitwebpackmy-vuecdmy-vuecnpminstallcnpmrundev脚手架安装好后,安装vuexcnpminstallvuex--save6.如何使用Vuex1。如何通过vue实现如下效果?这个小demo用Vue很容易实现,核心代码如下:点击{{count}}次,计数为{{evenOrOdd}}
......exportdefault{name:"HelloWorld",data(){return{count:0};},computed:{evenOrOdd(){returnthis.count%2===0?"偶数":"奇数";}},方法:{增量(){this.count=this.count+1;},减量(){this.count=this.count-1;},//只有当它是奇数时才加1incrementIfOdd(){if(this.count%2===1){this.count=this.count+1;}},//两秒后加1incrementAsync(){setInterval(()=>{this.count=this.count+1;},2000);}}}2.如何通过Vuex改造上面的代码?①创建一个store.js文件importVuefrom'vue'importVuexfrom'vuex'Vue.use(Vuex)conststore=newVuex.Store({state:{count:0},mutations:{//包含很多个对象直接更新状态函数INCREMENT(state){state.count=state.count+1;},DECREMENT(state){state.count=state.count-1;}},getters:{//当读取时属性值自动调用并返回属性值evenOrOdd(state){returnstate.count%2===0?"evennumber":"oddnumber";}},actions:{//包含多个对应的事件回调函数ObjectincrementIfOdd({commit,state}){//有条件的动作if(state.count%2===1){commit('INCREMENT')}},incrementAsync({commit}){//异步操作setInterval(()=>{commit('INCREMENT')},2000);}}})exportdefaultstore//使用exportdefault封装代码,以便外部引用②在main.js文件中引入store.js文件importstorefrom'./store'newVue({el:'#app',router,store,//注册vuex的store:所有的组件对象多了一个属性$storecomponents:{App},template:'
'})③新建模板HelloWorld.vue
点击{{count}}次,计数为{{evenOrOdd}}
由于store中的状态是响应式的,当Vue组件从store中读取状态时,如果store中的状态发生变化,相应的组件将相应地高效更新。在组件中调用存储中的状态就像在计算属性中返回它一样简单。更改存储中状态的唯一方法是显式提交更改。3、如何通过mapState等辅助函数优化上述代码?import{mapActions,mapGetters,mapState,mapMutations}from"vuex";...computed:{...mapState(["count"]),...mapGetters(["evenOrOdd"])}方法:{...mapActions(["incrementIfOdd","incrementAsync"]),...mapMutations(["increment","decrement"])}需要注意的一点:HelloWorld.vue文件中的increment函数名必须相同作为store.js文件的mutations可以写成...mapMutations(["increment","decrement"])只有在中间一致的情况下。同理,incrementIfOdd和incrementAsync也应该和store.js文件动作一致。七、使用Vuex的注意点1.如何在Mutations中传递参数首先在store.js文件Mutations中的add方法中添加一个参数n:{INCREMENT(state,n){state.count+=n;},DECREMENT(state){state.count--;}}然后修改HelloWorld.vue中按钮的commit()方法传入的参数increment(){returnthis.$store.commit("INCREMENT",2);},decrement(){returnthis.$store.commit("DECREMENT");}2.如何理解getters的含义getters从表面上看,你可以把他看成是一种在获取数据之前的重新编辑,相当于对数据的一次过滤和处理。getter类似于计算属性,因为getter的返回值根据其依赖项被缓存,并且仅当其依赖项的值发生变化时才重新计算。例如:对store.js文件中的count进行操作,在输出前先加100。首先需要在store.js中的Vuex.Store()中引入gettersgetters:{count:state=>state.count+=100}然后在HelloWorld.vue中配置computed。Vue构造函数中只能有一个computed属性,如果写多个属性,只有最后一个computed属性可用,所以需要用扩展运算符“...”修改上一节写的computed属性。computed:{...mapGetters(["count"])}3.actions和mutations的区别上面的actions和Mutations的作用基本相同。不同之处在于操作异步更改状态,而突变同步更改状态。同步的意义在于,每次mutation执行完后,可以对应一个新的state(和reducer一样),这样devtools就可以快照保存,然后就可以随便穿越了。如果你在devtoolon的情况下调用一个异步action,你可以清楚的看到它调用的mutation是什么时候被记录的,并且可以马上查看它们对应的状态----游鱼溪ps:如果想访问源码,请戳混帐地址。如果觉得文章对你有帮助,请点赞关注我的GitHub博客。非常感谢!参考文章vuex官方文档Vuex2.0源码分析