Map 헬퍼

컴포넌트에 연결된 스토어의 스테이트, 게터, 액션, 뮤테이션이 많아질 경우 코드가 복잡해지게 됩니다. 이러한 복잡한 코드를 간결하게 작성 가능하도록 Vuex는 Map 헬퍼를 제공합니다.

  • mapState
  • mapGetters
  • mapActions
  • mapMutations

Map 헬퍼와 전개 연산자를 사용해 객체의 속성으로 간편한 설정이 가능합니다.

// 사용 방법 1
...mapState(['books', 'cart'])
// 사용 방법 2
...mapMutations({
  changeBooks: 'setBooks'
})
// 사용 방법 3
...mapGetters({
  CartItemsCount: state => state.cart.length
})

BookList 컴포넌트에 Map 헬퍼를 활용하는 예를 살펴보겠습니다.

  1. vuex 모듈에서 Map 헬퍼를 불러옵니다.
  2. mapState 헬퍼를 사용해 스토어의 books를 가져와 계산된 속성으로 설정합니다.
  3. mapGetters 헬퍼를 사용해 스토어의 checkOutOfStock 동적 게터를 가져와 계산된 속성으로 설정합니다.
// components/BookList.vue

import { mapState, mapGetters } from "vuex"; // [1]

export default {
  name: 'BookList',
  computed: {
    ...mapState(['books']), // [2]
    // books() {
    //   return this.$store.state.books;
    // },
    ...mapGetters(['checkOutOfStock']), // [3]
    // checkOutOfStock() {
    //   return this.$store.getters.checkOutOfStock;
    // }
  }
}

컴포넌트에 바인딩 된 Map 헬퍼 내부에서 컴포넌트의 데이터에 접근해 처리할 수도 있습니다.







 




 
 
 




// components/BookList.vue

export default {
  name: 'BookList',
  data () {
    return {
      bookIndex: 2
    }
  },
  computed: {
    ...mapState({
      specificBook(state) {
        return state.books[this.bookIndex]
      }
    })
  }
}

주의!

Map 헬퍼 내부에서 this를 사용할 경우, 화살표 함수를 사용하면 안됩니다. 화살표 함수 내부의 this는 컴포넌트가 아닌 undefined 입니다.

computed: {
  ...mapState({
    specificBook: state => state.books[this.bookIndex] // ✖︎ this === undefined
  })
}

ShoppingCart 컴포넌트 또한 Map 헬퍼를 활용할 수 있습니다.







 
 
 
 









// components/ShoppingCart.vue

import { mapGetters } from "vuex";
export default {
  name: 'ShoppingCart',
  computed: {
    ...mapGetters({
      books: 'cartBooks',
      total: 'cartTotal'
    }),
    // books() {
    //   return this.$store.getters.cartBooks;
    // },
    // total() {
    //   return this.$store.getters.cartTotal;
    // }
  },
}

액션 또한 Map 헬퍼를 사용해 컴포넌트에 바인딩 할 수 있습니다.

  1. 스토어의 fetchBooks, addBookToCart 액션을 컴포넌트의 메서드로 바인딩합니다.
  2. 컴포넌트 생성 시점 훅 함수 내부에서 컴포넌트에 바인딩된 스토어의 액션을 활용할 수 있습니다.







 



 






// components/BookList.vue

import { mapState, mapGetters, mapActions } from 'vuex';
export default {
  name: 'BookList',
  // ...
  created() {
    this.fetchBooks().then(() => (this.loading = false)) // [2]
    // this.$store.dispatch("fetchBooks").then(() => (this.loading = false));
  },
  methods: {
    ...mapActions(['fetchBooks', 'addBookToCart']), // [1]
    // addBookToCart(book) {
    //   this.$store.dispatch("addBookToCart", book);
    // }
  }
}

ShoppingCart 컴포넌트의 스토어 액션 바인딩 예



 




 
 
 






// components/ShoppingCart.vue

import { mapGetters, mapActions } from "vuex";
export default {
  name: "ShoppingCart",
  // ...
  methods: {
    ...mapActions({
      purchageBook: "purchage"
    })
    // purchage() {
    //   this.$store.dispatch("purchage");
    // }
  }
};

ShoppingCart의 템플릿 코드에 사용된 $store.state.purchageStatus 또한 Map 헬퍼를 사용해 코드를 간소화 할 수 있습니다.

  1. vuex 모듈에서 mapState를 불러옵니다.
  2. mapState 헬퍼를 사용해 스토어의 purchageStatus 스테이트를 계산된 속성으로 설정합니다.
  3. 템플릿 코드에 계산된 속성 purchageStatus를 사용해 간소화 합니다.



 





 




 









<template>
  <div class="shopping-cart">
    <!-- ... -->
    <p v-if="purchageStatus">{{ purchageStatus }}</p> <!-- 3 -->
    <!-- <p v-if="$store.state.purchageStatus">{{ $store.state.purchageStatus }}</p> -->
  </div>
</template>

<script>
import { mapGetters, mapActions, mapState } from "vuex"; // [1]

export default {
  name: "ShoppingCart",
  computed: {
    ...mapState(['purchageStatus']), // [2]
    ...mapGetters({
      books: "cartBooks",
      total: "cartTotal"
    })
  },
  // ...
}
</script>