괴발개발

Vuex로 어플의 복잡한 콤포넌트 관리하기 (Vuex설치, state, getter!)

debbbie 2022. 9. 11. 10:10

 

0. Vuex를 설치하는 방법

-npm방식으로 설치 ( ES5와 ES6가 있는데 ES6로 해보쟈구): 터미널에 입력!

-공식 홈페이지

https://vuex.vuejs.org/installation.html

 

Installation | Vuex

Installation Direct Download / CDN https://unpkg.com/vuex@4 Unpkg.com provides NPM-based CDN links. The above link will always point to the latest release on NPM. You can also use a specific version/tag via URLs like https://unpkg.com/vuex@4.0.0/dist/vuex.

vuex.vuejs.org

npm i vuex@3.6.2

**참고로 vue 3.0 버전 공식주소**

https://vuejs.org/

 


Vuex로 어플의 복잡한 콤포넌트 관리하기 (Vuex설치, state, getter!)

2022/09/11

 

 

0-1.Vuex 폴더 일반적으로 아래 경로임!

src > store 폴더 생성 > 그 안에 stroe.js 생성

 

 

 

그 안에 vue와 vuex를 쓰겠다고 호출을 해줘야함

import Vue from 'vue'
import Vuex from 'vuex'

 

 

-use 플러그인(vue의 플러그인 기능임!) 을 사용해서 전역으로 vuex를 사용
(공식문서에 보면 나와있음)

Vue.use(Vuex);

 

 

-export로 store 선언해서 다른 콤포넌트에서도 이 store 변수를 사용할 수 있도록 함

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);

export const store = new Vuex.Store({
});


- main.js에서 store 변수를 사용할거기 떄문에, main.js파일에서 store.js파일에서 store 변수를 사용한다고 호출

 

import { store } from './store/store'

 

-그리고 위에서 store을 쓰기로 했으니, main.js파일에서 store 콤포넌트를 쓰면됨

(*ES6에서 배웠으니 간략하게 store이라고 쓰면됨)

 

new Vue({
  el: '#app',
  render: h => h(App),
  store
})

 

1.사용해야하는 이유?

-Vuex로 콤포넌트가 많아질때 효율적으로 관리하고,

-react의 문제점을 해결하기위한 flux패턴을 vue.js에서도 사용

-상태 관리가 필요한 state, getters, mautations, actions

-Helper를 사용하면 vuex활용이 편해짐

 

2.flux패턴이란?

-기존 페이스북 직원들이 사용했던 MVC라는 패턴은 복잡한 데이터 문제가 있음! (큰 앱들은 전체적인 데이터 흐름을

추적하기 어려워서 한가지가 바뀌어도 다른 기능들이 바뀐 기능을 추적하기 어려움)

**기존 Vue에서도 콤포넌트 간의 통신 방법을 props와 event를 사용 했던것과 비슷한것**

 

 

 

 

3.flux와 MVC의 패턴

-flux는 한 방향으로 호출하는 방면,

기존의 MVC는 model과 view가 자유롭게 통신이 되어서, 기능추가나 변경시, 어디에서 문제가 발생할지

알수 없고 업데이트 시에도 복잡하고 충돌이 날 가능성이 생긴다! 데이터의 흐름을 파악하기 어려움

 

 

그래서, flux를 사용하여서 , 데이터를 단방향으로만 처리할 수 있도록 함!

 

 

Vuex를 사용하지 않는다면, 추가로..

왜냐면 콤포넌트가 많아질수록, 이벤트를 어디서 송수신 했는지, 

빠르게 정확하게 파악이 어려움! (콤포넌트간 데이터 전달이 두루뭉실해짐, 복잡한 앱일수록 더더욱!)

 

 

 

4.Vuex 복잡한 콤포넌트관리와 상태관리

a.state, view, action

-state : data() => 여러 콤포넌트에서 사용하는 데이터

-view: template => 데이터를 표시하는 화면

-action: methods => 사용자에 입력하면 데이터 변경!

 

 

b. 콤포넌트 > 비동기로직(비동기 메서드) > 동기로직 (동기 메서드) > 상태

-비동기와 동기는 무엇이 다를까?

1.자바스크립트는 특정 코드의 연산이 종료 후 다음 코드를 실행하는게 아님, 
다음 코드를 먼저 실행함 
===> why? 특히 API사용시, get, reponse를 실행할때까지 기다리면 늦어질수도.
할수 있는 연산을 먼저 실행하자!

2.내가 원하는 순서가 있다면 콜백 함수로 비동기 처리방식을 보완해줘야함
callback함수를 사용하면, 데이터를 받은 시점에 원하는 다른 연산 실행하도록 가능

3.그러나 콜백도 비동기 처리를 위해 여러번 사용하게 된다면,
콜백안에 콜백안에 콜백안에 .... 콜백지옥이 생긴다.

콜백함수 {
	콜백함수{
    	콜백함수{
        	콜백함수{
            }
        }
    }
}


.....으악!으악!

===> 콜백안에 콜백을 넣지말고 promise를 사용해서,
콜백을 각각의 함수로 분리해준다. (받은 데이터값, 다음 함수명)
===> (이전 함수에서 받은 데이터값, 다음 함수명)===> 무한반복....

 

5.그래서 콜백함수에 빠지지 않고 promise를 어떻게 활용할까?

이번 포스팅에서도 적은 내용인데, 복습하자면 promise와 resolve와 then을 활용한다.

 

5-1.pormise는 상태가 있다!

=> promise함수를 적으면 아래와 같이 상태가 있음

a.함수가 완료될때까지 대기하고 있음 =>pending

b.함수가 완료되고, 결과 값이 어떤것이듯 return해줌 => resolve

c.함수를 실패하거나 어디선가 오류가 난 실패상태 => rejected

(+그리고 실패한걸 왜 실패했는지, catched로 잡을 수 있음!)

 

5-2.그래서 resolve는 언제 사용하는데?

=>resolve (완료)했을때 어떻게 보여줄것인지 (예.값을 보여준다),
rejected (실패) 했을때 어떻게 보여줄것 인지 (예.데이터를 받아오는데 실패했어요!라고 보여준다 등..) 설정 가능!

 

5-3.그럼 then은? promise를 여러개 엮을 때 사용한다.

 


1.Vuex

-state = data 여러 콤포넌트에서 공유가능 데이터

-getters = 연산된 state에 접근 computed

-miutations = state값 변경 이벤트 로직, methods

-actions = 비동기 로직선언! aysnc methods

 

2.state란?

-여러 콤포넌트에서 공유할 데이터

-예제. vue.js와 vuex에서 각각 메세지 

===Vue.js===

data:{
	message: 'apple'
}

===Vuex===

state: {
	message: 'apple'
 }

 

그렇다면 각각 메세지를 사용할때? 템플릿 태그 안에서 각각 사용할때,

===vue.js===

{{ message }}


===vuex===

{{ this.$store.state.message  }}

 

=>store을 전역으로 설정해둬서 this.$store가 사용 가능하게 됨

 

2.getters

위에서의 state값을 접근하고, computed처럼 미리 연산된 값을 접근

===store.js파일에서===
state:{
	num:100
},

getters:{
	simpleNum(state){
    	return state.num;
    },
    mutipleNum(state){
    	return state.num *2;
    }
    
}

===>getters에 두가지 메소드를 정의,
1.simplteNum인데 state값을 넣어서 state의 num속성을 가져오는것 하나랑
2.mulipleNum인데, state값을 넣어서 state의 num속성dml 2배 값을을 가져오는것 하나랑

 

각각을 다른 콤포넌트에서 가져올때~

아래와 같이 getters에서 연산된 state 를 가져올 수 있음!

{{  this.$store.getters.simpleNum  }}
{{  this.$store.getters.mutipleNum  }}

 

=>즉! store.js에서 state와 그 안에서 미리 계산된 getters를 편하게 자겨올 수 있다는것!

 

 

2.Todolist 파일에서 어떻게 적용할 수 있을까?

여러 콤포넌트에서 공통적으로 사용하는게 뭘까? 헤더나 푸터는 내용이 반복적으로 사용!

store.js에 headerTitle속성을 추가한다!

 

export const store = new Vuex.Store({
    state:{
        headerTitle : 'Just do it'
    }

});

 

해당 속성이 필요한 vue파일에 가서 {{}}로 추가, 기존의 헤더명은 삭제!

기존
<h1>여행 체크리스트</h1>

vuex를 사용
<h1>{{ this.$store.state.headerTitle}}</h1>

 

동일하게 타이틀이 뜨는걸로 볼 수 있다.

 

3.Todolist파일에서 todoItem도 모든 콤포넌트에서 공유되는

동일한 데이터이기 때문에 store.js에서 함께 공유할 수 있다!

 

- 예를 들어 App.vue에서 created를 적용하기 위해서

created(){
    if(localStorage.length > 0){
        for(let i =0; i <localStorage.length; i++){
          if (localStorage.key(i) !== 'loglevel:webpack-dev-server') {
          this.todoItems.push(JSON.parse(localStorage.getItem(localStorage.key(i))));
          }
        }
    }
  },

 

-store.js에서 storage라는 함수를 선언하고, created 넣기

const storage = {
	fetch(){
    	
    }

}를 사용하되,기존에 만들었던 created구문 넣기... 단 중복되는 created~는 제외

const storage = {
    fetch(){
    if(localStorage.length > 0){
        for(let i =0; i <localStorage.length; i++){
          if (localStorage.key(i) !== 'loglevel:webpack-dev-server') {
          this.todoItems.push(JSON.parse(localStorage.getItem(localStorage.key(i))));
          }
        }
    }
  },
    };

 

-다만 수정은 해주어야함, 1.배열로 값을 받아야함 2.범위 스코프가 다르기 때문에 현재의 this. todoItem만으로는 접근 불가

=>array를 선언하고, 

const arr = [];

=>array로 불러와야함

this.todoItems.push(JSON.parse(localStorage.getItem(localStorage.key(i))));
를
arr.push(JSON.parse(localStorage.getItem(localStorage.key(i))));

-arr값을 출력

const storage = {
    fetch(){
    const arr = [];
    if(localStorage.length > 0){
        for(let i =0; i <localStorage.length; i++){
          if (localStorage.key(i) !== 'loglevel:webpack-dev-server') {
          arr.push(JSON.parse(localStorage.getItem(localStorage.key(i))));
          }
        }
    }
    return arr;
  },
    };

 

- state에 출력하기

 

export const store = new Vuex.Store({
    state:{
        todoItem: storage.fetch()
    }

});

 

-todoList.vue에서 props 데이터 대신에 이전에 선언한 this.$store.state.todoItem을추가

(why? props data로 todoitemlist를 받아오니까!)

<li v-for="(todoItem, index) in this.$store.state.todoItem" v-bind:key="todoItem.item" class="shadow">