본문 바로가기
STUDY/VUE

[vue.js] veux 사용시 computed property 의 반복적인 get/set 선언을 줄이고 싶다 (using vuex-map-fields)

by simongs 2020. 9. 19.

▣ 고민사항

  • back-end 만 하다가 오랜만에 front-end 쪽을 보니까 신세계이다.
  • 한 페이지 내에 아래와 같이 vuex와 동기화 처리할 변수(상태 변수)가 여러개 이다.
  • 만약 name, age, city... 10개의 항목이 있다면 유사한 코드 블럭이 10번 반복된다.
  • 이를 축약시켜줄 수 있는 라이브러리가 있을까?
  • 유사한 고민 : Using get/set Computed property with mapState, mapMutation in Vuex
<div>
    <input v-model="name"> // computed property (with vuex) 의 양방향 바인딩 
<div>    

<script>
computed: {
  name: {
    get() {
      return this.$store.state.namespace_001.name;
    },
    set(value) {
      this.$store.commit("namespace_001/name", value);
    }
  },
  // 늘어납니다.
  age: { 
      get() {},
    set() {},
  },
  // 늘어납니다.
  city : {
      get() {},
    set() {},
  }
}
</script>

▣ computed property 에 대한 간단 정리

Define Style 및 특징

  • sum() 은 함수이지만 sum 과 같은 속성(property) 접근 방식을 사용해도 정상 실행이 된다.
    • (Define Style 1) 참고
    • 그러한 이유로 Computed Property 라고 부른다.
    • Vue 인스턴스의 모든 Option정보를 다루는 $options 를 통해 함수를 확인가능하다.
  • computed라는 단어가 주는 느낌으로 계산되어진 정보를 가져오기만 할거 같은 느낌이지만 set메소드를 지정하면 쓰기 작업도 가능하다.
    • (Define Style 2) 참고
    • 즉 이 기능을 활용해서 특정 computed property 의 2-way(양방향) 바인딩 구현이 가능하다.
    • 요 스타일로 여러 변수를 선언할 때 코드가 늘어지는 것을 해결해보고 싶었다.
    • vuejs 공식사이트 - computed 속성의 setter 함수
  • 가장 중요한 특징은 cache 가 되어서 내부 값이 변하기 전에는 캐싱된 값을 리턴합니다.

Sample Source

<div id="sample">
    {{ sum }} 원
    {{ amount }} 원
</div>

var vm = new Vue({
    el : "#example",
    data : { num : 0 },
    computed : {
        // (Define Style 1) vm.sum에 대한 getter 함수 정의 
        sum : function() {
            var sum = 합계;
            return sum;
        },
        // (Define Style 2) vm.amount 에 대한 getter/setter 함수 정의
        amount : {
            get : function() {
                return this.num * 2;
            },
            set : function(amt) {
                this.num = amt;
            }
        }
    }

▣ 해결방안

  • vuex-map-fields 라이브러리를 사용한다

vuex-map-fields 란

  • Vuex Store에 저장된 feild 에 대해 양방향으로 데이터 바인딩을 가능하게 한다.
  • 아래 Reference 에 정의되어 있는 github 주소를 통해서 자세한 내용을 확인 가능합니다.
  • 사용법 중 활용한 일부케이스에 대한 설명만 적어봅니다.

namespace 로 구분된 vuex 에서 사용법

  • 기본적으로는 모듈 내의 mutations, getters는 global namespace 하위에 등록이 된다.
  • 모듈 간의 mutations, getters 의 네이밍 충돌을 각 모듈별로 "namespaced" 속성을 활성화 할수 있다.

Store (fooModule namespace)

  • state에 정의된 field 들에 대한 getField(getter), updateField(setter)를 만들어준다.
import Vue from 'vue';
import Vuex from 'vuex';

import { getField, updateField } from 'vuex-map-fields';

Vue.use(Vuex);

export default new Vuex.Store({
  // ...
  modules: {
    fooModule: {
      namespaced: true,
      state: {
        foo: '',
        test: '',
        name: '',
      },
      getters: {
        getField,
      },
      mutations: {
        updateField,
      },
    },
  },
});

Component (Style 1)

  • createHelpers 를 통해서 fooModule namespace 의 getters, mustations 접근
<template>
  <div id="app">
    <input v-model="foo">
    <input v-model="name">
  </div>
</template>

<script>
import { createHelpers } from 'vuex-map-fields';

// `fooModule` is the name of the Vuex module.
const { mapFields } = createHelpers({
  getterType: 'fooModule/getField',
  mutationType: 'fooModule/updateField',
});

export default {
  computed: {
    ...mapFields(['foo', 'name']),
  },
};
</script>

Component (Style 2)

  • 직접적인 명시를 통한 fooModule namespace 의 getters, mustations 접근
  • 개인적으로는 요 스타일 선호.
<template>
  <div id="app">
    <input v-model="foo">
    <input v-model="name">
  </div>
</template>

<script>
import { mapFields } from 'vuex-map-fields';

export default {
  computed: {
    // `fooModule` is the name of the Vuex module.
    ...mapFields('fooModule', ['foo', 'name']),
  },
};
</script>
혹시 틀린 부분이나 수정이 필요한 정보가 있다면 댓글남겨주시면 수정하도록 하겠습니다.

Reference

댓글