官方说明:Vuex是专门为vue.js应用开发的状态管理模型。1.Vuex是做什么的?什么是状态管理?简单的说:多个组件需要的所有变量都可以存储在一个对象中,然后把这个对象放在顶层的vue实例中,其他组件就可以使用了。这样多个组件就可以共享这个对象的所有属性。有的同学觉得这么简单,我们在vue的顶层定义一个对象就可以实现共享了?我们发现,虽然可以获取到数据,但是如果某个组件中的数据发生了变化,我们如何修改数据,让这个数据在其他组件中保持最新呢?我们的vuex就是提供一个插件,在多个组件之间共享状态,可以做到实时响应。2.Vuex使用vuex是管理组件间通信的插件,所以使用前必须安装。2.1.安装1)使用脚本导入2)使用包管理npminstallvuex--save//yarnaddvuex注意:vuex必须依赖vue2.2使用,构建store实例创建store文件夹,新建index.jsimportVuefrom"vue";importVuexfrom"vuex";Vue.use(Vuex);//使用vuexexportdefaultnewVuex.Store({state:{},mutations:{},getters:{},actions:{},modules:{}})在main.js中,挂载storeimportstorefrom'./store'newVue({router,render:h=>h(App)})//等同于//Vue.prototype.$store=store2.3,usingstate//state中定义的Statusstate:{statue:'online'}//在components中使用
组件中的数据:{{$store.state.status}}
//在js中使用mounted(){console.log(this.$store.state.status)}3.Vuex3.1的五个核心,statestatestorevuex的基本用于存储变量的数据。单状态树Vuex使用单状态树,即一个对象包含所有状态数据。state是一个构造函数选项,它定义了我们需要的所有基本状态参数。组件中引用状态数据的方式:1)通过vue的computed获取vuex的stateexportdefaultnewVuex.Store({state:{online:true}})computed:{status(){returnthis.$store.state.online}}store时的数据of被更改,计算属性将被重新计算,相关的DOM将被更新。2)如果需要使用多个参数,使用computed属性,这样会使代码有些冗余和复杂。这时候我们就可以使用mapState这个辅助功能了。//state中有很多数据,在一个组件中被引用exportdefaultnewVuex.Store({state:{online:true,per:[{name:'qq',age:18}],role:'administrator'}})//import{mapState}from'vuex'exportdefault{name:'App',computed:mapState({onl??ine:state=>state.online,per:'per',//组件中的'per'相当于state.perrole:'role'//'role'相当于state.role})}vuex使用单个状态树来管理应用层的所有状态,单个状态树可以让我们找到一个片段以最直接的方式呈现一个状态,并且后续的维护调试过程也可以非常方便的进行管理和维护。3.2.吸气剂在状态突变后从商店获得一些状态。一般有两种使用方式:1)返回结果只依赖state中的数据exportdefaultnewVuex.Store({state:{count:2,},getters:{//返回两倍数据countDouble(state){returnstate.count*2}}})//在组件中引用
获取countDouble:{{$store.getters.countDouble}}
//运行结果获取countDouble:4这里,$store.getters.countDouble的使用和上面的$store.state.count是一样的。2)getters中返回的变异结果依赖于某个getters中某个属性的返回结果count*2}//返回两次countDouble的数据countDoubleT(state,getters){returngetters.countDouble*2}}})//在组件中引用
获取countDouble:{{$store.getters.countDoubleT}}}/div>//运行结果得到countDouble:83.3,更新mutationsvuex的store状态的唯一方法:SubmitMutation。Mutations主要包括两部分:字符串事件类型和回调函数,回调函数的第一个参数是状态。1)mutation中的方法被commit调用,不传参:exportdefaultnewVuex.Store({state:{count:2,},mutations:{incrs(state){//count加1state.count++}}})//组件每点击一次按钮就会调用{{$store.state.count}},计数加一次。2)Mutations传递参数当我们点击Add按钮时,我们指定每次添加的值,如下:exportdefaultnewVuex.Store({state:{count:2,},mutations:{addNum(state,n){//countplus1state.count+=n}}})//组件调用{{$store.state.count}}//运行结果每点击一次按钮,计数加5。最后一个实例传递了一个参数。如果我们需要传递多个参数,如何实现呢?3)mutations传递多个参数exportdefaultnewVuex.Store({state:{count:2,},mutations:{addNum(state,payload){//payload为传递的参数对象state.count+=payload.count}}})//componentcall{{$store.state.count}}exportdefault{methods:{addTen(){this.$store.commit({type:'addNum',count:10,...//可以传入任意个数的参数})}}}//运行结果上每点击一次按钮,count加10,以上方法为特殊提交包突变。包含类型属性的对象,使用整个提交对象作为有效负载。3.4.actionsmutations提交更新数据的方法必须是同步的。如果异步使用就会出现问题,然后在项目开发中经常使用异步更新,比如网络请求数据。Actions类似于mutations,功能大致相同,但是actions是用来代替mutations进行异步操作的。1)actions的基本用法actions:{aUpdateCount(context){setTimeout(()=>{//使用timer模拟异步操作context.commit('updateCount')},2000)}},mutations:{updateCount(state){state.count=5201314},}//使用{{$store.state.count}}/component/Runresult点击按钮,两秒后计数值更新为5201314。值得注意的是,使用action异步更新数据时,仍然需要通过mutations中的方法,state中的数据只能通过mutations中的方法进行修改。在突变中调用方法,使用提交调用。在actions中调用方法,使用dispatch来调用。2)异步更新时,也可以带参数//功能:点击按钮,指定count动作的修改值:{aUpdateCount(context,payload){setTimeout(()=>{//使用timer模拟异步操作context.commit('updateCount',payload)},2000)}},mutations:{updateCount(state,payload){state.count=payload},}//使用{{$store.state.count}}//点击运行结果的按钮,两次后更新计数值seconds:我爱前端3)传入异步参数actions:{//传入promiseupdateData(context,payload){returnnewPromise((resolve,reject)=>{setTimeout(()=>{resolve('我学会了')},2000)})},}//在组件中调用methods:{ok(){this.$store.dispatch('updateData').then((res)=>{console.log(res)})},}//点击运行r的按钮结果,两秒后打印:学了3.5,modulesmodules的意思是modules,vue用的是单状态树,项目越来越大,store的数据越来越多,不方便数据管理和维护,代码会变得臃肿。因此,使用模块将数据划分到相应的模块中,不仅方便开发,也提高了代码的可读性。1)模块简单地使用importVuefrom'vue'importVuexfrom'vuex'import{Increase}from'./mutation_type.js'Vue.use(Vuex)exportdefaultnewVuex.Store({state:{},actions:{},getters:{},mutations:{},modules:{a:{state:{},getters:{},mutations:{},actions:{}},b:{state:{},getters:{},mutations:{},actions:{}}},})//也可以组织为constmoduleA={state:{},getters:{},mutations:{},actions:{}}constmoduleB={state:{},getters:{},mutations:{},actions:{}}Vue.use(Vuex)exportdefaultnewVuex.Store({state:{},actions:{},getters:{},mutations:{},modules:{a:moduleA,b:moduleB},})2)如何使用模块中的数据?constmoduleA={state:{aName:'我是模块a的数据'},getters:{},mutations:{},actions:{}}//引用{{$store.state.a.aName}}中component3)在module中调用mutations中的方法,如何调用?$store.commit('aChangeName')调用了模块中mutations中的方法,和之前完全一样。程序会先从一级store中查找方法,如果找不到则继续在模块中查找。4)在模块的getters中调用方法$store.getters.getName。需要注意的是,getters中的方法都是对state中数据的突变。如果模块的getters方法需要根存储中的状态怎么办?getName(state,getters,rootState){//state表示当前模块的状态//getters表示当前模块的getters//rootState表示根store中的状态}5)模块中actions中的方法可以仅在使用commit调用mutations中的方法时调用该模块中的mutations方法不能调用外部方法。4.Vuex数据响应原理Vuexstore中的状态是响应式的。当state中的数据发生变化时,vue组件会自动更新。这就需要我们遵守vuex对应的一些规则:提前在store中初始化需要的属性。用人类的话来说,必须在状态中定义的属性才能响应。如果以后添加或删除它们,它们将无法响应。举个栗子:mutations:{changeName(state){state.info.name='一个爱学习的前端人'},addAdrs(state){state.info['address']="陕西西安"},}{{this.$store.state.info}}此时点击修改名称时,可以实现响应,但是点击“添加地址”按钮时,页面没有响应,但是可以看到数据已在开发人员模式下更改。我们想要响应式,如何实现呢?addAdrs(state){state.info['address']="陕西西安"//修改为:vue.set(state.info,'address','陕西西安')},同理,如果你想删除age属性,不能用delete做响应式,需要改成Vue.delete。示例:响应式删除年龄属性deleteAge(state){//deletestate.info.age//修改为Vue.delete(state.info,'age')},//组件内容{{this.$store.state.info}}5.类型常量mutation中定义了很多事件类型,即方法名。当项目越来越大,Vuex管理的状态越来越多,需要更新的状态也越来越多,这意味着Mutations中的方法名越来越多。当方法太多时,使用它们会花费很多时间。通过记忆或来回切换文件查找方法名很容易出错,所以建议大家使用常量。就算方法名错了,也是错的,程序也不会异常。如://新建mutation_type.js文件//导出一个常量exportconstIncrease='increase'//store.js文件importVuefrom'vue'importVuexfrom'vuex'import{Increase}from'./mutation_type.js'Vue.use(Vuex)exportdefaultnewVuex.Store({state:{count:2,},mutations:{[Increase](state){state.count++},}})//组件内容{{$store.state.count}}import{Increase}from'./store/mutation_type'sxportdefault{methods:{add(){this.$store.commit(Increase)}}}时,只记得增加或在mutation_type.js文件中查找即可。