programing

모듈 네임스페이스와 함께 Vuex 유형 상수를 사용하는 방법

bestcode 2022. 8. 24. 23:56
반응형

모듈 네임스페이스와 함께 Vuex 유형 상수를 사용하는 방법

Vuex 모듈은 다음과 같습니다.

//modules/things.js
const state = {
  firstThing: 'abc',
  secondThing: 'def',
};

const getters = {
  getFirstThing: state => state.firstThing,
  getSecondThing: state => state.secondThing,
};

const mutations = {
  setFirstThing: (state, payload) => state.firstThing = payload,
  setSecondThing: (state, payload) => state.secondThing = payload
};

const actions = {};

export default {
  namespaced: true,   // <------
  state,
  mutations,
  actions,
  getters
};

사용하고 있다namespaced: true 플래그를 지정하여 다음과 같이 이 모듈을 조작할 수 있습니다.

this.$store.state.things.firstThing             // <-- return abc here
this.$store.commit('things/setFirstThing', 10)
this.$store.getters['things/getFirstThing']     // <-- return abc here

Vuex의 공식 예시와 같은 상수를 사용하고 my factor my factor my factor.modules/things.js다음과 같은 파일:

export const Types = {
  getters: {
    GET_FIRST_THING: 'GET_FIRST_THING',
    GET_SECOND_THING: 'GET_SECOND_THING',
  },
  mutations: {
    SET_FIRST_THING: 'SET_FIRST_THING',
    SET_SECOND_THING: 'SET_SECOND_THING',
  }
};

const getters = {
  [Types.getters.GET_FIRST_THING]: state => state.firstThing,
  [Types.getters.GET_SECOND_THING]: state => state.secondThing,
};

const mutations = {
  [Types.mutations.SET_FIRST_THING]: (state, payload) => state.firstThing = payload,
  [Types.mutations.SET_SECOND_THING]: (state, payload) => state.secondThing = payload
};

이름 공간 접두사를 사용해야 합니다.

this.$store.commit('things/' + Types.mutations.SET_FIRST_THING, 10);
this.$store.getters['things/' +  + Types.getters.GET_FIRST_THING]  

모듈 이름 공간 접두사를 포함할 경우Typesconstant, 문자열 접두사를 사용해야 합니다.things/돌연변이/액션/게터 선언:

const getters = {
  ['things/' + Types.getters.GET_FIRST_THING]: state => state.firstThing,
  ['things/' + Types.getters.GET_SECOND_THING]: state => state.secondThing,
};

어떻게 피할 수 있을까요?

네임스페이스를 디세블로 할 수 있습니다.namespaced: false접두사가 붙은 상수만 사용합니다.

export const Types = {
  getters: {
    GET_FIRST_THING: 'THINGS_GET_FIRST_THING',    // your namespace without '/' slash
    GET_SECOND_THING: 'THINGS_GET_SECOND_THING',
  },
  // ...
}

- 잘 될 거야.

하지만 네가 여전히 계속하고 싶다면namespaced: truemodule 및 use 상수에서는 public private의 가지 상수 유형을 정의할 수도 있습니다.

export const Types = {                                               // <-- public
  getters: {
    GET_FIRST_THING: 'things/GET_FIRST_THING',
    GET_SECOND_THING: 'things/GET_SECOND_THING',
  },
  mutations: {
    SET_FIRST_THING: 'things/SET_FIRST_THING',
    SET_SECOND_THING: 'things/SET_SECOND_THING',
  }
};

const _types = removeNamespace('things/', Types);                    // <-- private

그 후 비공개 사용_typesVuex 모듈 내부만:

const getters = {
  [_types.getters.GET_FIRST_THING]: state => state.firstThing,       
  [_types.getters.GET_SECOND_THING]: state => state.secondThing,
};

//...

및 공개Types외부 모듈:

// some-component.vue
this.$store.commit(Types.mutations.SET_FIRST_THING, 10);
this.$store.getters[Types.getters.GET_FIRST_THING]
// ...

또, 심플한 실장removeNamespace새로운 기능namespace-helper.js파일:

export default function removeNamespace(namespace, types){
  return _.reduce(types, (typeObj, typeValue, typeName) => {
    typeObj[typeName] = _.reduce(typeValue, (obj, v, k)=>{
      obj[k] = v.replace(namespace, '');
      return obj;
    }, {});
    return typeObj;
  }, {});
}

@hedin의 답변이 훌륭하게 작용했습니다, 감사합니다!

문제는 다음과 같습니다.

  1. 타이프 스크립트를 사용하고 있습니다.

  2. 너무 장황해서 가독성을 해칠 수 있습니다.하지만 나에게는 활자 안전이 더 중요하기 때문에 활자 확인을 위해 다소 장황한 말을 하는 것은 참을 수 있다.

그의 디자인에 영감을 받아, 나는 그것을 타이프하여 장황함을 줄였다.

(Vue 3 (컴포지션 API 포함)+ Vuex 4 (네임슬레이드 모듈 포함)를 사용하고 있습니다.

먼저, 저는namespace-helper.ts다음과 같이 표시됩니다.

import _ from "lodash";

type NamespaceHelper = {
  [name: string]: string;
};

// Enhanced from @hedin, see https://stackoverflow.com/a/47646215/1360592
export default (
  namespace: string,
  types: any,
  section: "getters" | "actions" | "mutations",
): NamespaceHelper => {
  return _.reduce(
    types,
    (typeObj: NamespaceHelper, typeValue, typeName) => {
      if (typeName === section) {
        return _.reduce(
          typeValue,
          (obj: NamespaceHelper, v, k) => {
            obj[k] = v.replace(namespace, "");
            return obj;
          },
          {},
        );
      }
      return typeObj;
    },
    {},
  );
};

다음으로 스토어 모듈에는 다음과 같은 기능이 있습니다.

const namespace = "things";

// For external use
export const Types = {
  getters: {
    GET_FIRST_THING: `${namespace}/GET_FIRST_THING`,
    GET_SECOND_THING: `${namespace}/GET_SECOND_THING`,
  },
  actions: {
    DO_FIRST_THING: `${namespace}/DO_FIRST_THING`,
    DO_SECOND_THING: `${namespace}/DO_SECOND_THING`,
  },
  mutations: {
    SET_FIRST_THING: `${namespace}/SET_FIRST_THING`,
    SET_SECOND_THING: `${namespace}/SET_SECOND_THING`,
  },
};

// For internal use in the same store
const _getters = removeNamespace(`${namespace}/`, Types, "getters");
const _actions = removeNamespace(`${namespace}/`, Types, "actions");
const _mutations = removeNamespace(`${namespace}/`, Types, "mutations");

// getters
const getters: GetterTree<MyStoreState, RootState> = {
  [_getters. GET_FIRST_THING]: (state) => {
    return state.blah;
  },
  ...
};

// actions
const actions: ActionTree<MyStoreState, RootState> = {
  [_actions.DO_FIRST_THING]: ({ commit }) => {
    // do stuff here
    ...
    commit(_mutations.SET_FIRST_THING);
  },
};

// mutations
const mutations = {
  [_mutations.SET_FIRST_THING]: (state: MyStoreState) => {
    state.blah = "foo";
  },
};

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations,
};

컴포넌트에서 사용하는 방법은 다음과 같습니다.

<script lang="ts">
// imports go here, not shown for brevity

import { Types } from "@/store/modules/things";

export default defineComponent({
  name: "Thing",
  setup(props) {
    const store = useStore<RootState>();

    // I prefer singular for consuming getters and actions externally.
    const { getters: getter, actions: action } = Types;

    const firstThing = computed<ThingType>(() =>
      store.getters[getter.GET_FIRST_THING],
    );

    store.dispatch(action.DO_FIRST_THING);

    return {
      firstThing,
    };
  },
});
</script>

언급URL : https://stackoverflow.com/questions/47646176/how-to-use-vuex-types-constants-with-module-namespace

반응형