vuex的使用方法与规范

324 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天

vuex使用方法与规范

我们一般将所有需要管理的数据都存入到一个store对象中,更加方便后期管理(state单一状态树)

如果获取state中数据时,想要获取其变化后的值,需要在getters中进行操作(比如增减变化、数据过滤等等),调用时不用加括号,以属性的方式调用

getters: {
    powerCounter(state) {
        return state.counter * state.counter
    },
    //方法中还可以传入第二个参数,第二个参数就是getters本身,可以通过这个本身在getters方法中调用另一个getters方法
    dulPowCounter(state, getters){
        return getters.state * getters.state
    },
    //如果想在方法中传入自定义值,需要将返回值写为方法
    customizePowCounter(state){
        return (num) => {
            return state.counter ** num;
        }
    }
}
​
//App.vue中使用方法
{{$store.getters.customizePowCounter(3)}}

mutations补充:

  • vuex的store状态的更新唯一方式就是提交Mutation,提交Mutation有两种方式:

    • 第一种:
    • //这里sayHello是事件类型,后面的部分是回调函数,param2是第二个参数
      sayHello(state, param2){
                  state.message += param2;
              }
      
    • 在App.vue中调用mutations中的方法时,如果想要传参,需要为commit提供后续参数:
    • $store.commit('sayHello', param2)//在methods中调用时,记得写成$store.commit()形式
      
    • 传入的第二个参数被称为是mutation的载荷(Payload)
    • 如果又很多个参数,则需要将多个参数以对象的形式封装传入
  • Mutation包含包括两部分:字符串的事件类型(type)和一个回调函数(handler)

    • 我们就可以利用这两部分,进行另一种特殊的提交封装:
    • 第二种:
    • //app.vue的methods中
      sayHello(param2) {
          this.$store.commit({
              type: 'incrementCount',
              param2
          })
      }
      
    • 这种方式传输过去的第二个参数是以对象形式传递的,需要用如下方式获取:
    • sayHello(state, param2){
                  state.message += param2.param2;
              }
      
    • 当然,这里的param2更建议写成payload
  • 注:如果是在mutations的方法中为对象添加新的属性,则新的属性不在vuex的监听范围内,不能实现响应式(和数组中直接通过下标修改数组元素类似),如果是删除属性,delete操作符也同样不在监听范围内

    • 如果要添加属性,可以用set方法:
    • Vue.set(state.info, 'address', 'los')
      
    • 如果要删除属性,可以用delete方法:
    • Vue.delete(state.info, 'age')
      
  • 方法变量抽离写法:在mutations中定义方法并使用时,方法名(type)容易写错,官方建议我们将其抽离,具体做法如下:

    • 在store文件夹下创建mutations-types.js文件,在其中定义方法名,导出后在App.vue和index.js中导入并引用:
    • //mutations-types.js
      export const SAYHELLO = 'sayHello'
      //App.vue
      import {SAYHELLO} from './store/mutations-type.js'//或者用*全部导入
      methods: {
          sayHello(){
              this.$store.commit(SAYHELLO)
          }
      }
      //mutations中(记得在index.js的头部引入常量)
      mutations: {
          [SAYHELLO](state){
              state.message += param2.param2;    
          }
      }
      
vuex-action的使用

通常情况下,Vuex要求我们Mutation中的方法必须是同步方法,主要原因是当我们使用devtools时,devtools可以帮助我们捕捉mutation的快照,但如果是异步操作,那么devtools将不能很好的追踪这个操作什么时候会被完成

这时候我们就要用到actionl来处理异步操作:

  1. 在actions中定义方法,将异步操作放入:

    actions: {
            //这里要传入context对象
            actionsTimeOut(context){
                setTimeout(() => {
                    context.commit('mutationTimeOut')
                },1000)
            }
        },
    
  2. mutations中做异步后的同步操作:

    mutations: {
            mutationTimeOut(state){
                //dosth
            }
        },
    
  3. App.vue中将操作分发至actions:

    methods: {
        timeOut(){
          //使用dispatch分发至actions
          this.$store.dispatch('actionTimeOut')
        }
      }
    

    注:actions中也可使用payload,为第二个参数

想要在异步操作完成后对外界调用处进行通知,有两种方式:

第一种:dispatch时传入一个回调函数,在actions中commit下一行调用该回调函数,以起到通知的效果

第二种(推荐):在action的方法中返回Promise,在commit操作后调用resolve方法,回到methods中,在dispatch分发后紧接着调用then方法

//App.vue
methods: {
    timeOut(){
      //使用dispatch分发至actions
      this.$store.dispatch('actionsTimeOut').then(mes => console.log(mes))
    }
  }
  
//store/index.js
actions: {
        //这里要传入context对象,也可以利用解构写成如下形式:
        actionsTimeOut({commit}){
            return new Promise((resolve, rejeck) => {
                setTimeout(() => {
                    context.commit('mutationTimeOut')
                    resolve('done');
            },1000);
            })
        }
    },
getters: {
        mutationTimeOut(state){
            //dosth
        }
    },
Vuex-Module的使用

Vue使用单一状态树,意味着很多状态(变量)都要交给Vuex来管理,当应用变得非常复杂时,store对象就会变得相当臃肿,为了解决这个问题,Vuex允许我们将store分割成模块,而每个模块允许拥有自己的state、mutations、actions、getters等等

//定义moduleA
const modulaA = {
    state: {
        name: 'zhangsan'
    },
    mutations: {
        fun(){
            //dosth
        }
    }
}
//引入moduleA
modules: {
        a: modulaA
    }
​
//App.vue中的引用
//state中状态要记得.模块名
//mutations中的方法不需要.模块名,在子模块中找不到会自动去父模块中去找
​
{{$store.state.a.name}}
$store.commit('fun')
​
//调用getters中方法与mutations中类似,同样不需要.模块名,但注意以下情况
//子模块getter中访问父模块state属性
getter: {
    fun(state, getters, rootState){
        //通过rootState.pamas的方式获取
    }
}
​
//actions中方法的context对象不包括父模块,这也意味着commit只能针对自己所在模块的mutations
//要用action访问父模块的state,使用rootState.paramname
store项目结构
  • store

    • index.js //组装模块并导出store的地方,state就放在这里

    • actions.js //根级别的action

    • mutations.js //根级别的mutation

    • modules

      • modulesA.js //A模块部分
      • modulesB.js //B模块部分