Vue.js Vuex utility features, module

강정우·2023년 4월 5일
0

vue.js

목록 보기
32/72
post-thumbnail
post-custom-banner

mapGetters

  • 이는 store drilling을 방지하고자 나온 개념이다. 우선 아래와 같은 예시를 봐보자.
<template>
  <h3>{{counter}}</h3>
</template>

<script>
export default {
    computed:{
        counter(){
            return this.$store.getters.finalCounter
        }
    },
}
</script>
  • 사실 위 코드는 큰 무리는 없지만 this. 키워드 밑으로 $store... 가 너무 귀찮다면 mapGetters를 이용해봐도 좋겠다.
<template>
  <h3>{{finalCounter}}</h3>
</template>

<script>
import {mapGetters} from "vuex";

export default {
    computed:{
        ...mapGetters(['finalCounter'])
    },
}
</script>
  • computed 객체 내부에서 이 함수를 사용할 수 있다.

    • 연산 프로퍼티를 직접 정의하는 대신 여기서 mapGetters를 호출하면 이것이 객체를 반환한다.
    • 그리고 spread 연산자를 사용하면 computed 프로퍼티 내부로 객체를 퍼뜨릴 수 있다.
    • 즉 mapGetters는 연산 프로퍼티에 병합되는 객체를 제공한다.
  • mapGetters가 제공하는 객체는 computed 프로퍼티로 구성되어 있는 객체이며 자동으로 정의된다.

  • mapGetters는 배열을 인수로 받는다.

    • 여기에 getters의 getter 이름을 문자열로 나열하는데 원래 computed 프로퍼티로 받아와야 하는 getter의 이름을 넣으면 된다.
    • 따라서 이 경우에는 finalCounter가 되지만 때에 따라 여러 개의 게터가 될 수도 있다.
    • 이제 컴포넌트에서 finalCounter computed 프로퍼티를 제공하며 자동으로 finalCounter getter를 가리킨다.
    • 이제 {{ }} 구문에 finalCounter를 자유롭게 쓸 수 있다. finalCounter가 연산 프로퍼티의 이름이기 때문이다.

mapGetters를 사용하면 특히 컴포넌트에서 게터를 여러 개 사용할 경우 저장소를 불필요하게 파고들 필요 없이 코드를 효율적으로 작성할 수 있다.

mapActions

  • 얘도 마찬가지로 컴포넌트에서 actions를 매핑할 수 있다.
<template>
  <button @click="addOne">Add 2</button>
</template>

<script>
export default {
    methods:{
        addOne(){
            this.$store.commit("increament");
        }
    }
}
</script>
<template>
  <button @click="inc">Add 2</button>
  <button @click="incs({value:10})">Add 10</button>
</template>

<script>
import {mapActions} from "vuex";

export default {
    methods:{
        ...mapActions({
            inc:'increment',
            incs : 'increase'
        })
    }
}
</script>
  • mapGetters와 방법은 같고 동작 원리도 같다 그리고 추가적으로 mapGetters도 가능한데 일단 여기서는 이름을 따로 매핑하여사용했다.

Module

  • 저장소 및 상태 등이 점차 많아짐에 따라 Vuex가 제공하는 여러 유용한 기능 중에 모듈을 설정해서 저장소를 여러 모듈로 나누는 기능을 사용하면 좋다.

  • 애플리케이션에 하나의 저장소가 있고 그 저장소가 다수의 모듈로 이루어져 코드를 관리하기 쉬워지는 것이다.

    • 모듈을 설정해두지 않으면 자동으로 하나의 루트 모듈과 루트 상태만 가지게 되며 다음에 모듈을 원하는 만큼 추가할 수 있다.
    • 카운터에 대한 모듈 하나 인증에 대한 모듈 하나를 가질 수도 있고 인증은 루트 모듈의 루트 상태에 둔 채 추가 모듈에 카운터를 아웃소싱할 수도 있다.
  • 우선 기존의 모듈을 분리한다.

const customedModule = {
	state(){},
    mutations:{},
    actions:{},
    getters:{}
}
  • 이 해당 모듈을 createStore 객체에 이식해주면 된다.
const store = createStore({
	modules:{
    	식별자 : customedModule
    }
    ...
})
  • 기본적으로 저장소로 결합된 모듈들은 같은 레벨에 결합된다.

  • 따라서 해당 저장소에 모듈을 결합하면 모듈을 만들기 전처럼 게터 등을 저장소에서 바로 찾을 것이다.
    그래서 모듈을 사용해도 액션을 디스패치하고 게터를 전처럼 사용할 수 있다.

  • 하지만 분명 다른점이 있을 것이다. 무엇일까?

local module

  • mutations, actions, getters는 전역(global)이라 메인 저장소에서 전처럼 액세스할 수 있지만 state는 모듈의 지역 상태이기 때문에 모듈 내에 상태는 해당 모듈에만 적용되는 것이다.

    • 즉 게터에서 local state를 받지 못하게 된다.
  • 말을 어렵게 했는데 그냥 한마디로 state가 지역변수처럼 바뀌어 다른 모듈에서는 해당 state를 사용할 수 없다는 뜻이다.

  • 그렇다면 이를 어떻게 타파할 수 있을까 바로 rootState, rootGetters이다.

const customedModule = {
	state(){
    	return {
        	counter : 0
        }
    },
    getter:{
    	testAuth(rootState, rootGetters) {
            return rootState.isLoggedIn
        },
    }
}

name space 지정하기

  • local state 외에도 모듈 전체를 지역 모듈로 만들 수 있다.
    바로 네임스페이스를 이용해서 여러 모듈을 분명히 분리하는 것인데 어떤 경우에 사용할까

  • 애플리케이션이 커지면서 이름이 중복되는 경우가 생긴다. 한 저장소 내 다른 모듈에서 getters나 actions등에 같은 이름을 사용하게 될 수 있다.

    • 예를들어 customedModule에 login action이 있다면 메인 저장소에 있는 login 액션과 충돌한다.
    • 왜냐면 state를 제외하고 모든 것이 하나의 객체로 결합된 상태이기 때문이다.
const customedModule = {
  namespaced:true
  ...
}
  • namespaced를 true로 설정하면 state뿐만이 아니라 모듈 전체가 store로부터 분리되어야 한다는 걸 Vuex에 알린다.
    즉, state를 제외하고 하나의 객체로 결합되던 것이 이제는 아예 분리가 된다는 뜻이다.

  • 네임스페이스는 store의 modules에 모듈을 추가할 때 지정하는 키이다. 이 경우 numbers가 counterModule의 네임스페이스인것인데 이제 이 네임스페이스를 이용해 모듈 내 action과 getter등을 다뤄야 한다.

분할된 모듈 사용하기

<template>
    <h3>{{counter}}</h3>
  <p>We do more...</p>
</template>

<script>
export default {
    computed:{
        counter(){
            return this.$store.getters.normalizedCounter;
        }
    }
}
</script>
  • 전에 이렇게 사용했다면 이제는
<template>
    <h3>{{counter}}</h3>
  <p>We do more...</p>
</template>

<script>
export default {
    computed:{
        counter(){
            return this.$store.getters['numbers/normalizedCounter'];
        }
    }
}
</script>
  • 특수 기호를 포함한 특수 프로퍼티 이름을 대괄호 안에 입력해 액세스해야 한다.
    • 여기에 프로퍼티 이름을 문자열로 전달하는데 이때 프로퍼티 이름은 예전 프로퍼티 이름 앞에 네임스페이스를 입력한다.

mapGetter까지 함께 사용해보기

<template>
  <h3>{{finalCounter}}</h3>
</template>

<script>
import {mapGetters} from "vuex";

export default {
    computed:{
        ...mapGetters('numbers', ['finalCounter'])
    },
    methods:{
      	addOne() {
            // this.$store.commit("increase", {value:10});
            this.$store.dispatch({
                type: "numbers/increase",
                value:10
            })
        }
	    ...mapActions('numbers', {
    	  inc:'increment',
      	incs : 'increase'
    	})
  	}
}
</script>
  • namespace를 사용할 시 첫 번째 인수는 네임스페이스 두 번째 인수는 네임스페이스 내 게터(액션)의 배열이다. 혹은 객체가 될 수 있고

파일 분할

profile
智(지)! 德(덕)! 體(체)!
post-custom-banner

0개의 댓글