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

 

+ Recent posts