【Vue】010. Vuex状态管理(二)

242 阅读3分钟

01. mutation拓展

(1)提交方式

  • 要使用 mutation,必须通过commit提交,这里有以下两种方式进行提交

    • 普通方式提交

      • type作为第一参数,对象作第二参数,commit(type,[payload])
    • 对象风格的提交方式

      • 直接传递一个对象,但必须有type字段,且可以添加任意额外字段,这些字段将作为payload传入

      type字段:表示提交的 mutation 方法

    // 普通方式
    store.commit('myMutation', {
        num: 10,
        color: 'red'
    });
    // 对象风格
    store.commit({
        type: "myMutation",
        num: 10,
        color: 'red'
    });
    

(2)响应规则

  • mutation 也需要遵守一些注意事项:

    • 最好提前在你的 store 中初始化好所有所需属性

    • 当需要在对象上添加新属性时,可以使用

      mutation: {
      	myMutation(state, newVal){
              // 第一种方式
              Vue.set(state, newProp, newVal);
              // 第二种方式:替换
              this.replaceState({ ...state, newProp: newVal });
          }
      }
      

02. action拓展

(1)有何区别

  • mutation 提交的是同步操作

  • mutation 可以直接改变状态 state

    • mutation 的第一个参数是 state
  • action 可以包含任意异步操作

    • action 提交的是 mutation,而不是直接变更状态

    • action 的第一个参数是 context

(2)提交方式

  • Action 通过 dispatch方法进行提交,方式同Mutation

    // 普通方式
    store.dispatch("myAction", {
        num: 10
    });
    
    // 对象风格
    store.dispatch({
    	type: "myAction",
    	num: 10
    });
    
    

03. module拓展

(1)关于state的问题

  • gettermutation接收的第一个参数state,是全局的还是模块的?

    • 是模块的state,也就是局部的state

  • 如何访问全局的state和getter?

    • getter中,可以通过**第三个参数rootState第四个参数rootGetters**来访问到全局的state和getter
      • mutation中,不可以访问全局的satat和getter,只能访问到局部的state

      • action中,通过context中的 context.rootState访问到全局的state,context.rootGetters访问到全局的getter

(2)关于命名空间的问题

  • 为什么需要使用命名空间?

    • 默认情况下,模块内部的actionmutationgetter是注册在全局命名空间的

    • 如果多个模块中action、mutation的命名是一样的,那么提交mutation、action时,将会触发所有模块中命名相同的mutation、action

    • 如果要使你的模块具有更高的封装度和复用性,你可以通过添加namespaced: true 的方式使其成为带命名空间的模块

  • 命名空间的模块内如何提交全局的mutation和action?

    • { root: true }作为第三参数传给 dispatch 或 commit 即可
    this.$store.dispatch('myAction', null, { root: true })
    this.$store.commit('myMutation', null, { root: true })
    
  • 怎么在带命名空间的模块内注册全局的action?

    actions: {
        // 这个 moduleAction 定义在模块中,注册在全局
        moduleAction: {
            root: true,
            handler (context, data) {
            	...
            }
    	}
    }
    

(3)在组件内使用的问题

  • 如何使用?

    this.$store.state.moduleA.state1;
    this.$store.commit('moduleA/myMutation')
    this.$store.dispatch('moduleA/myAction')
    
  • 如何使用辅助函数映射模块里的属性和方法?

    • 第一种方式

      computed: {
          ...mapState({
              state1: state => {
                  return state.moduleA.state1
              },
              state2: state => state.moduleA.state2
          })
      },
      methods: {
          ...mapMutations(['moduleA/myMutation'])
      }
      
    • 第二种方式

      • 指明模块的路径
      computed: {
          ...mapState('moduleA', {
          	state1: state => state.state1,
              state2: state => state.state2
          }) 
      },
      methods: {
      	...mapMutations('moduleA', ['myMutation'])  
      }
      
    • 第三种方式

      • 首先使用createNamespacedHelpers创建基于某个命名空间辅助函数
      import { createNamespacedHelpers } from 'vuex';
      // 创建基于 moduleA模块 的辅助函数
      const { mapState, mapMutations } = createNamespacedHelpers('moduleA');
      export default {
          computed: {
              // 在 `moduleA` 中查找
              ...mapState({
                  state1: state => state.state1,
                  state2: state => state.state2
              })
          },
          methods: {
              // 在 `moduleA` 中查找
              ...mapMutations(['myMutation'])
          }
      }
      

本人前端小菜鸡,如有不对请谅解