Vuex를 다시 일하면서 쓸일이 생겼다..
ㅎㅎ.. 알고는 있지만 정확하게 이해하고 있는거 같진 않아서 다시 정리해보고자 한다!
(백엔드 위주로 하고싶은데.. 참,,, FE 를 놓지 못하게 한다 회사가)
1. Vuex 란?
Vue의 상태(State) 관리 도구
상태: 여러 컴포넌트 간에 공유되는 데이터 속성
서비스가 복잡해 졌을 때, 데이터를 다른 컴포넌트에 공유해야 할 수도 있음
컴포넌트 레벨이 깊어지거나 관계가 복잡했을 때 상태관리 도구는 유용하게 사용
컴포넌트에서 API를 불러와 화면을 그리는 것이 아닌, Vuex에서 API를 불러옴
Vuex의 State에 API로부터 받아오 데이터를 담음
State를 컴포넌트에 전달하여 화면을 그림
Vuex 구성요소
state : 여러 컴포넌트에 공유되는 data
getters : 연산된 state 값을 접근하는 속성 computed
mutations : state 값을 변경하는 이벤트 로직, 메서드 methods
actions : 비동기 로직을 선언하는 async mehods
2.State
3.Getter
state값을 접근하는 속성이자 computed() 처럼 미리 연산된 값을 접근하는 속성
4. Mutations 이란?
state의 값을 변경 할 수 있는 유일한 방법이자 메서드
mutations는 commit()으로 동작
// store.js
state: { storeNum: 10 },
mutations: {
modifyState(state, payload) {
console.log(payload.str);
return state.storeNum += payload.num;
}
}
// App.vue
this.$store.commit('modifyState', {
str: 'passed from payload',
num: 20
})
mutations로 상태를 변경해야하는 이유?
특정 시점에 어떤 컴포넌트가 state를 접근하여 변경한 건지 확인하기 어렵기 때문
따라서, 뷰의 반응성을 거스르지 않게 명시적으로 상태변화를 수행
반응성, 디버깅, 테스팅 혜택
src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import {fetchNewsList} from '../api/index.js';
// Vuex는 플러그인 형식으로 제공
Vue.use(Vuex);
// 인스턴스
export const store = new Vuex.Store({
state : {
news: []
},
mutations: {
// 첫번째 인자 state, 두번째 인자 action으로부터 전달받은 값
SET_NEWS(state, news) {
// state에 데이터 전달
state.news = news;
}
},
actions: {
// mutation에 접근할 수 있도록 context 인자가 제공
FETCH_NEWS(context) {
fetchNewsList()
.then(response => {
// mutation에 data를 넘길 수 있음
context.commit('SET_NEWS', response.data);
})
.catch(error => {
console.log(error);
})
}
}
})
src/views/NewsView.vue
<template>
<div>
// store의 state에 접근
<div v-for="item in this.$store.state.news" > {{ item.title }} </div>
</div>
</template>
<script>
export default {
created() {
// action 호출
this.$store.dispatch('FETCH_NEWS');
}
}
</script>
<style>
</style>
5. Actions 이란?
비동기 처리 로직을 선언하는 메서드
비동기 로직을 담당하는 mutations
데이터 요청, Promise, ES6 , async 와 같은 비동기 처리는 모두 actions에 선언
actions에 비동기 로직을 선언해야하는 이유?
언제 어느 컴포넌트에서 해당 state를 호출하고, 변경했는지 규격화를 하여 확인하기 위해
mutations에 시간차를 두고 state를 변경하는 경우 추적하기 어려움
그러므로 mutations속성에는 동기처리 로직만 넣어야함
Vuex에서 api 호출은 Actions에서 하기
비동기 호출
Backend API를 호출하여 Mutations에 넘겨주기 위한 속성
Vuex 구조상 actions에서 state에 바로 담을 수 없게 되어 있음
Actions는 Vue Component에서 Dispatch라는 api로 호출 가능
// store.js
mutations: {
setData(state, fetchData) {
state.product = fetchData;
},
},
actions: {
fetchProductData(context) {
// api 호출 이후 응답을 state에 넣음
return axios.get('https://domaion.com/products/1')
.then(response = context.commit('setData', response));
}
}
// App.vue
methods: {
incrementCounter() {
this.$store.dispatch('fetchProductData');
}
}
6. Module
state, getters, mutations, actions가 많아질 수록 코드의 가독성은 떨어지고 유지보수는 힘들어짐
별도의 파일로 모듈화 하는 것이 편함
actions.js, mutations.js 파일에 각 코드를 옮기기
7. Helper
7.1 mapStates
Vuex에 선언한 states 속성을 뷰 컴포넌트에 더 쉽게 연결해주는 헬퍼
<template>
<div>
<div v-for="item in ask"> {{ item.title }} </div>
</div>
</template>
<script>
import {mapState} from 'vuex';
export default {
computed: {
// store의 state에 접근하여 ask를 가져옴
// spread 연산자로 computed에 ask를 뿌림
...mapState({
ask: state => state.ask,
}),
},
created() {
this.$store.dispatch('FETCH_ASK');
},
}
</script>
<style>
</style>
7.2 mapGetters
Vuex에 선언한 getters 속성을 뷰 컴포넌트에 더 쉽게 연결해주는 헬퍼
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// mix the getters into computed with object spread operator
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
...mapGetters({
// map `this.doneCount` to `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})
7.3 mapMutations
Vuex에 선언한 mutations 속성을 뷰 컴포넌트에 더 쉽게 연결해주는 헬퍼
// App.vue
import { mapMutations } from 'vuex';
methods: {
...mapMutations(['clickBtn']),
atuhLogin() {},
displayTable() {}
}
// store.js
mutations: {
clickBtn(state) {
alert(state.msg);
}
}
<button @click="clickBtn">popup message</button>
7.4 mapActions
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>
참고:
https://greedysiru.tistory.com/808
Vue.js - Vuex, Vuex 모듈화 및 state 적용
본 내용은 인프런 장기효(캡틴판교)님의 Vue.js 완벽 가이드 - 실습과 리팩토링으로 배우는 실전 개념 강의를 토대로 작성하였습니다. 1. Vuex Vue의 상태(State)관리 도구 상태: 여러 컴포넌트 간에 공
greedysiru.tistory.com
https://vuex.vuejs.org/guide/getters.html#the-mapgetters-helper
Getters | Vuex
Getters Sometimes we may need to compute derived state based on store state, for example filtering through a list of items and counting them: computed: { doneTodosCount () { return this.$store.state.todos.filter(todo => todo.done).length } } If more than o
vuex.vuejs.org