[Vue.js] 11 Vuex Helper
              
          2021. 9. 24. 09:58ㆍStudy/Vue.js
반응형
    
    
    
  Vuex Helper
- Vuex의 각 속성들을 더 쉽게 사용하는 방법 - Helper
- Store에 있는 아래 4가지 속성들을 간편하게 코딩하는 방법
- state -> mapState
- getters -> mapGetters
- mutations -> mapMutations
- actions -> mapActions
 
Helper의 사용법
- helper를 사용하고자 하는 vue 파일에서 아래와 같이 해당 helper를 로딩
- 만약 헬퍼를 사용하지 않았다면, State에 정의 된 num에 접근하려면 this.$store.state.num 와 같이 접근해야 한다.
- 생소하게 보이는 mapState앞에 있는 ...은 ES6의 Object Spread Operator이다.
//App.vue
import { mapState } from 'vuex';
import { mapGetters } from 'vuex';
import { mapMutations } from 'vuex';
import { mapActions } from 'vuex';
export default {
   computed() {
       ...mapState(['num']),
       ...mapGetters(['countedNum'])
  },
   methods: {
       ...mapMutations(['clickBtn']),
       ...mapActions(['asyncClickBtn'])
  }
}mapState, mapGetters
- mapState
- vuex에 선언한 state 속성을 뷰 컴포넌트에 더 쉽게 연결해주는 헬퍼
- vuex에서 mapState 함수를 가져와서 ... 연산자로 연결하고, 배열리터럴로 확장해서 사용한다.
- vuex store에 선언된 state에 this.$store.state로 접근하지 않아도 됨
- 또, vue 템플릿에서 state안에있는 num 접근할 때도 this.num으로 바로 접근 가능하다.
 
// App.vue
import { mapState } from 'vuex';
computed() {
   ...mapState(['num'])
   // num() { return this.$store.state.num; } 를 대체함
}
// store.js
state: {
   num: 10
}<!-- <p>{{ this.$store.state.num }}</p> -->
<p>{{ this.num }}</p>- mapGetters
- vuex에 선언한 getters 속성을 뷰 컴포넌트에 더 쉽게 연결해주는 헬퍼
- vuex store에 선언된 getters에 this.$store.getters로 접근하지 않아도 됨
- getters는 vuex를 적용하기 전 사용하던 computed 속성이라고 생각하면 된다.
 
// App.vue
import { mapGetters } from 'vuex';
computed: {
   ...mapGetters(['reverseMessage'])
}
// store.js
getters: {
   reverseMessage(state) {
       return state.msg.split('').reverse().join('');
  }
}<!-- <p>{{ this.$store.getters.reverseMessage }}</p> -->
{{ this.reverseMessage }}ES6 Spread 연산자를 쓰는 이유
- 싱글파일 컴포넌트 구조의 각 컴포넌트에서 정의된 computed 속성이 있을 것이고,
- 거기에 Vuex store에 정의된 getters를 사용해야하는 상황이 있을 것이다.
- 이때, ... 연산자를 통해 mapGetters를 연결해줘야 컴포넌트에서 computed 속성과 Vuex의 store에 등록된 getters를 함께 사용할 수 있다.
mapMutations, mapActions
- mapMutations
- Vuex에 선언한 mutations 속성을 뷰 컴포넌트에 더 쉽게 연결해주는 헬퍼
- 컴포넌트에서 버튼 클릭시 컴포넌트의 methods에 clickBtn이 정의 되어있는 것 처럼 동작한다.
- 하지만 실제로는 ...mapMutations를 통해서 Vuex Store에 등록된 함수를 쓴다.
- 따라서, Vuex에 정의된 state.msg가 alert로 뜨게 될 것이다.
 
 
- Vuex에 선언한 mutations 속성을 뷰 컴포넌트에 더 쉽게 연결해주는 헬퍼
// App.vue
import { mapMutations } from 'vuex';
methods: {
   ...mapMutations(['clickBtn']),
   authLogin() {},
   displayTable() {}
}
// store.js
mutations: {
   clickBtn(state) {
       alert(state.msg);
  }
}
<button @click="clickBtn">popup message</button>- mapActions
- Vuex에 선언한 actions 속성을 뷰 컴포넌트에 더 쉽게 연결해주는 헬퍼
- 마찬가지로 컴포넌트에서 버튼 클릭으로 methods에 등록된 delayClickBtn을 호출한다.
- methods에는 Spread Operator로 store의 actions에 정의된 delayClickBtn을 등록한다.
 
 
- Vuex에 선언한 actions 속성을 뷰 컴포넌트에 더 쉽게 연결해주는 헬퍼
// App.vue
import { mapActions } from 'vuex';
methods: {
   ...mapActions(['delayClickBtn'])
}
// store.js
actions: {
   delayclickBtn(context) {
       setTimeout(() => context.commit('clickBtn'), 2000);
  }
}
<button @click="delayClickBtn">delay popup message</button>Helper의 유연한 문법
- Vuex의 선언한 속성을 그대로 컴포넌트에 연결하는 문법
// 배열 리터럴
...mapMutations([
   'clickBtn',    //'clickBtn': clickBtn
   'addNumber'    //addNumber(인자)
])- addNumber(인자)의 경우 배열리터럴로 넘기는 string에 선언을 안해도 알아서 넘겨준다!
- Vuex에 선언한 속성을 컴포넌트의 특정 메서드에다가 연결하는 문법
// 객체 리터럴
...mapMutations({
   popupMsg: 'clickBtn'    // 컴포넌트 메서드 명 : Store의 Mutation 명
})- 컴포넌트에서 사용하는 메서드와 Store의 Mutation 명이 다를 경우 객체 리터럴을 사용해서 등록할 수 있다.
Helper 함수가 주는 간편함
- demoStore.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.store({
   state: {
       price: 100
  },
   getters: {
       originalPrice(state) {
           return state.price;
      },
       doublePrice(state) {
           return state.price * 2;
      },
       triplePrice(state) {
           return state.price * 3;
      }
  }
})- 헬퍼를 사용하지 않고 Vuex를 적용한 컴포넌트 - Demo.vue
<template>
   <div id="root">
       <p>{{ originalPrice }}</p> //100
       <p>{{ doublePrice }}</p>   //200
       <p>{{ triplePrice }}</p>   //300
   </div>
</template>
<script>
 export default {
     computed: {
         originalPrice() {
             return this.$store.getters.originalPrice;
        },
         doublePrice() {
             return this.$store.getters.doublePrice;
        },
         triplePrice() {
             return this.$store.getters.triplePrice;
        },
    },
};
</script>- Vuex 의 헬퍼함수를 사용하면 반복 코드를 줄이고 편하게 Vuex store에 접근할 수 있다.
- template영역에 this.로 스토어에 바로 접근해도 되지만 영역에 표현식을 줄이는 것을 권고한다.
- 스크립트영역에서 store로 값을 받아온다.
<script>
 import { mapGetters } from 'vuex';
 export default {
     computed: {
         ...mapGetters(['originalPrice', 'doublePrice', 'triplePrice'])
    },
};
</script>Vuex 프로젝트 구조화 및 모듈화
- 애플리케이션에 스토어를 적용해서 사용하다가 보면 금방 스토어의 덩어리가 커지므로 데이터(상태)의 성격별로 스토어를 모듈화 해주면 훨씬 관리하기가 수월하다.
방법 1 - 속성별 파일로 구조화
- store 디렉토리 구조
- store
- getters.js
- mutations.js
- store.js
 
 
- store
* mutations.js
const addOneItem = (state, todoItem) => {
 const obj = {completed: false, item: todoItem};
 sessionStorage.setItem(todoItem, JSON.stringify(obj));
 state.todoItems.push(obj);
}
const removeOneItem = (state, payload) => {
 sessionStorage.removeItem(payload.todoItem.item);
 state.todoItems.splice(payload.index, 1);
}
const toggleOneItem = (state, payload) => {
 state.todoItems[payload.index].completed = !state.todoItems[payload.index].completed;
 sessionStorage.removeItem(payload.todoItem.item);
 sessionStorage.setItem(payload.todoItem.item,
                        JSON.stringify(payload.todoItem));
}
const clearAll = (state) => {
 state.todoItems = [];
 sessionStorage.clear();
}
export { addOneItem, removeOneItem, toggleOneItem, clearAll }* store.js
import Vue from 'vue';
import Vuex from 'vuex';
import * as getters from './getters';
import * as mutations from './mutations'
Vue.use(Vuex);
export const store = new Vuex.Store({
 state: {
   todoItems: storage.fetch()
},
 getters,
 mutations
})방법 2 - 앱이 비대해져서 1개의 store로는 관리가 힘들 때 modules 속성 사용
- 모듈별로 필요한 store 속성들을 모아서 관리한다.
- store 디렉토리 구조
- store
- moduels
- todoApp
 
- store.js
 
- moduels
 
- store
store.js
import Vue from 'vue';
import Vuex from 'vuex';
import todoApp from './modules/todoApp';
Vue.use(Vuex);
export const store = new Vuex.Store({
 modules: {
   todoApp
}
});
./modules/todoApp
const storage = {
    fetch() {
        const arr = [];
        if (sessionStorage.length > 0) {
            for (let i = 0; i < sessionStorage.length; i++) {
                if (sessionStorage.key(i) !== 'loglevel:webpack-dev-server') {
                    arr.push(JSON.parse(sessionStorage.getItem(sessionStorage.key(i))));
                }
            }
        }
        return arr;
    },
};
const state = {
   todoItems: storage.fetch(),
}
const getters = {
   storedTodoItems(state) {
       return state.todoItems;
  }
}
const mutations = {
   addOneItem(state, todoItem) {
       const obj = {completed: false, item: todoItem};
       sessionStorage.setItem(todoItem, JSON.stringify(obj));
       state.todoItems.push(obj);
  },
   removeOneItem(state, payload) {
       sessionStorage.removeItem(payload.todoItem.item);
       state.todoItems.splice(payload.index, 1);
  },
   toggleOneItem(state, payload) {
       state.todoItems[payload.index].completed = !state.todoItems[payload.index].completed;
       sessionStorage.removeItem(payload.todoItem.item);
       sessionStorage.setItem(payload.todoItem.item, JSON.stringify(payload.todoItem));
  },
   clearAll(state) {
       state.todoItems = [];
       sessionStorage.clear();
  }
}
export default { state, getters, mutations }반응형
    
    
    
  'Study > Vue.js' 카테고리의 다른 글
| [Vue.js] 09 ES6 (0) | 2021.09.24 | 
|---|---|
| [Vue.js] 07 SFC(Single File Component) (0) | 2021.09.24 | 
| [Vue.js] 05 Template (0) | 2021.09.23 | 
| [Vue.js] 03 Router (0) | 2021.09.23 | 
| [Vue.js] 02 Component (0) | 2021.09.23 |