7.vuex_0
了解Vuex背景Vuex是专门为Vue.js应用开发的一种状态管理模式。它使用集中存储来管理应用程序所有组件的状态,并使用相应的规则来确保状态以可预测的方式变化。Vuex也被集成到Vue官方的调试工具devtoolsextension中,提供了零配置穿越调试、状态快照导入导出等高级调试功能。Vuex是一个提供多个组件之间共享状态的插件,状态有反应。单页状态管理State:状态。(可以看作是数据中的一个属性)View:视图层可以根据State的变化显示不同的信息。Actions:主要是用户的各种操作:点击、输入等,都会引起状态的变化。当前计数器:{{counter}}
多-页面状态管理(vuex)不同界面上的Action都想修改同一个状态。我们现在要做的就是将共享状态提取出来交给vuex。之后,各个组件按照规定的规则进行访问、修改等操作。Vuex状态管理传说Vue组件可以直接去mutations(但不推荐这样做)。Mutations中的操作都是同步操作。如果有异步操作,就会在action中进行操作。操作完成后,会提交给mutations进行同步操作。Devtools无法跟踪异步操作。Devtools是Vue开发的一款浏览器插件,可以帮助记录每次状态修改的记录。Vuex基本上使用了Vuex的核心概念,StateVuex,使用单个状态树来管理应用程序级别的所有状态。单一的状态树可以让我们以最直接的方式找到某个状态的片段,在后续的维护调试过程中也可以非常方便的进行管理和维护。状态是响应式的,当状态中的数据发生变化时,Vue组件会自动更新。getter类似于组件中的计算属性。当数据在页面上使用之前必须经过一系列更改时,将使用计算属性。同样,如果需要对状态中的数据进行操作并显示在页面上,则使用getters属性。常量存储=新Vuex。Store({state:{students:[{id:110,name:'why',age:18},{id:111,name:'kobe',age:21},{id:112,name:'lucy',age:25},{id:113,name:'lilei',age:30},]},getters:{//获取年龄大于20的学生人数。greateragesCount:state=>{returnstate.students.filter(s=>s.age>=20).length}}})如果我们已经有了年龄大于20岁的所有学生的列表,则将getter作为参数并传递参数getters,那么代码可以像这样写getters:greaterAgesstus.length}}getters默认不能传参。如果要传递参数,只能让getter返回另外一个函数。更新MutationVuex的store状态的唯一方式:提交MutationMutation主要包括两部分:字符串事件类型(type);一个回调函数(handler),回调函数的第一个参数是state。Mutation基本使用mutation的定义:mutations:{increment(state){state.count++}}通过mutation更新increment:function(){this.$store.commit('increment')}Mutation传递参数通过mutation更新数据,我们可能希望携带一些额外的参数。该参数称为突变的有效负载(Payload)。只有一个参数时,参数decrement(state,n){state.count-=n;}decrement:function(){this.$store.commit('decrement',2);}如果参数不是一个,一般以对象的形式传递,即payload是一个对象。从对象中检索相关信息。changeCount(state.pay1oad){state.count=payload.count;}changeCount:function(){this.$store.commit('changeCount',{count:0});}MutationcommitstyleVue还提供了另一种风格,是一个包含type属性的对象this.$store.commit({type:'changeCount',count:100})Mutation中的处理方式是将整个commit对象作为payload,所以代码没有变化,还是如下:changeCount(state,pay1oad){state.count=pay1oad.count}变异响应规则预先状态中初始好的属性是响应式的。之后,如果要修改(添加)状态中的数据,它是响应式的。有两种方式:方式一:使用Vue.set(obj,'newProp',123);方法二:使用新对象重新赋值旧对象App.vue
我的个人信息:{{info}}
store-->index.jsconststore=newVuex.Store({state:{info:{name:'why',age:18}},mutations:{updateInfo(state,payload){//学习教程中说这样的修改不是响应式的,但是修改后是响应式的实践。state.info['height']=payload.height;//方法一:Vue.set()Vue.set(state.info,'height',payload.height);//方法二:给info对象赋新值state.info={...state.info,'height':payload.height}}}});Mutation常量类型背景随着项目的增长,Vuex管理的状态越来越多,需要更新的情况越来越多,这意味着Mutation中的方法越来越多。方法太多,用户需要花费大量的经验去记住这些方法,甚至在多个文件之间来回切换,检查方法名,即使没有复制,也有可能出现错别字。一个非常常见的解决方案是使用常量而不是Mutation事件类型。这些常量可以放在单独的文件中,方便管理,让整个app的所有事件类型一目了然。具体操作可以创建一个文件:mutation-types.js,在里面定义常量。在定义常量时,可以使用ES2015中的风格,使用常量作为函数名。mutation-types.jsexportconstUPDATE_INFO='UPDATE_INFO';store-->index.jsimportVuexfrom'vuex'importVuefrom'vue'import*astypesfrom'./mutation-types'Vue.use(Vuex);conststore=newVuex.Store({state:{info:{name:'why',age:18}},mutations:{[types.UPDATE_INFO](state,payload){state.info={...state.info,'height':payload.height}}}});App.vueMutation同步函数Vuex要求Mutation中的方法必须是同步方法。原因是在使用devtools的时候,devtools可以帮助我们捕捉突变的快照。如果是异步操作,devtools无法很好地跟踪操作何时完成。通常,不要在突变中执行异步操作。ActionAction基本上定义了Action类似于Mutation,但它是用来代替Mutation进行异步操作的。Action的基本使用代码如下:conststore=newVuex.Store({state:{count:0},mutations:{increment(state){state.count++;}}actions:{increment(context){context.commit('增量');}}});context是一个对象,具有与store对象相同的方法和属性。可以使用context来进行commit相关的操作,也可以获取context.state等。Actions是定义好的,如果Vuex中有异步操作,那么我们可以在Actions中完成。如果Action的分发调用了action中的方法,那么就需要使用dispatch。它还支持传递有效载荷。//App.vuemethods:{increment(){this.$store.dispatch('increment',{cCount:5});}}//store-->index.jsmutations:{increment(state,payload){state.count+=payload.cCount;},actions:{increment(context,payload){setTimeout(()=>{context.提交('增量',有效载荷)},5000);}}Action在Action中返回Promise,我们可以将异步操作放在一个Promise中,成功或失败后调用相应的resolve或reject。store-->index.jsactions:{increment(context){returnnewPromise((resolve)=>{setTimeout(()=>{context.commit('increment');resolve()},1000);})}}App.vuemethods:{increment(){this.$store.dispatch('increment').then(res=>{console.log('updateoperationcompleted');})}}模块识别Vuex的ModuleVue使用一个单状态树也意味着许多状态将由Vuex管理。当应用程序变得非常复杂时,存储对象可能会变得相当臃肿。为了解决这个问题,Vuex允许将store拆分成模块(Module),每个模块都有自己的state、mutation、action、getter等。constmoduleA={state:{...},mutations:{...},动作:{...},吸气剂:{...}constmoduleB={状态:{...},突变:{...},动作:{...}}conststore=newVuex.store({modules:{a:moduleA,b:moduleB}})store.state.a//->moduleA的状态store.state.b//->moduleB的状态本地状态对象作为第一个参数。store-->index.jsconstmodule=(state:{count:0},mutations:{increment(state){state.count++;},}getters:{doubleCount(state){returnstate.count*2;}复制代码}}conststore=newVuex.store({state:{gCount:111},modules:{a:moduleA,b:moduleB}})App.vue注:虽然,我们的doubleCount和increment都是在对象内部定义的。但是调用的时候,直接通过this.$store调用的Module的Actions还是写的。本地状态是通过context.state暴露出来的,根的状态节点是context.rootState。constmoduleA={actions:{incrementIfoddonRootSum({state,commit,rootState}){//上下文对象的解构if((state.count+rootState.count)%2===1){commit('increment');}}}项目组织结构官方建议:state不要分开。