Vuex Store

이재원·2021년 9월 6일
0

Vuex Store

전역으로 데이터를 저장하여 여러 컴포넌트에서 접근하여 사용 가능

설치방법

Command 창에서 아래와 같이 명령어 수행

npm install vuex

기본환경 구성

  1. src/ 경로 하위에 store 폴더를 생성 후 index.js 파일을 만든다.
  2. 아래 기본 코드 추가
import Vue from 'vue';
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
    state:{
        todoList:[]
    },
    // 동기적 로직 setter로 생각하면됨
    mutations:{

    },
    // 비동기 로직 추가 시간이 오래 걸리는 작업(서버데이터 받기 , 타이머 등)
    actions:{
       
    },
    // 다른 컴포넌트에서 store.getters.getcounter 나 ...mapGetters 로 접근 가능   
    getters:{

    }
});
  1. main.js에 2번에서 생성한 index.js를 import 하여 사용한다.
import Vue from 'vue'
import App from './App.vue'
import router from '@/router/router.js'
import store from '@/store/index.js'
Vue.config.productionTip = false

new Vue({
  router,
  store, // import한 store 추가 
  render: h => h(App),
}).$mount('#app')

store 프로퍼티

1. state

전역으로 사용할 프로퍼티를 선언 후 다른 컴포넌트나 vue 파일에서 state에서 선언된 프로퍼티 값 가져오기
state에 carList를 선언 후

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

Vue.use(Vuex);

export default new Vuex.Store({
    // 전역으로 사용할 프로퍼티를 선언
    state:{
        carList:[
            {id:1,name:'k9'},
            {id:2,name:'k7'},
            {id:3,name:'k3'},
        ]
    },
});            

컴포넌트에서 this.$store.state.carList 로 carList에 접근이 가능 하다

<template>
  <div>
      {{getList}}
  </div>
</template>

<script>
export default {
    computed:{
        getList(){
            return this.$store.state.carList;
        }
    }
}
</script>

2. mutations

state에 선언되어있는 데이터를 변경하려면 mutations 함수를 정의하고 함수안에 state를 접근하여 변경해야 한다.

전달받을 함수명을 다음과 같이 선언 한다. ADD_CAR(state,car)

  • 첫 번째 파라미터는 state 이며
  • 두번 째 파라미터는 전달받을 데이터 이다.
import Vue from 'vue';
import Vuex from 'vuex'
Vue.use(Vuex);

export default new Vuex.Store({
    // 전역으로 사용할 프로퍼티를 선언
    state:{
        carList:[
            {id:1,name:'k9'},
            {id:2,name:'k7'},
            {id:3,name:'k3'},
        ]
    },
    // 동기적 로직 setter로 생각하면됨
    mutations:{
        ADD_CAR(state,car){
            console.log("ADD_CAR");
            state.carList.push(car);
        },
        DELETE_CAR(state,name){
            state.carList=state.carList.filter((car)=>{  
                console.log(name);
                return car.name!=name;
            });
            console.log(state.carList)
        },        
    },
});

컴포넌트에서 this.$store.commit() 함수를 이용하여 mutations에 선언한 함수를 호출하여 파라미터를 전달하여 store의 state의 값을 변경할 수 있다.

this.$store.commit('ADD_CAR',{name:this.inputValue});

  • 첫 번째 파라미터는 mutations에 선언한 함수이름
  • 두 번째 파라미터 전달할 데이터
<template>
  <div>
    <div v-for="(car,index) in carList" :key="index">
        <p>car 이름{{car.name}}</p>    
    </div>
    <input type="text" v-model="inputValue" placeholder="추가할 자동차 이름을 입력하세요">
    <button v-on:click="addcar()">자동차 추가</button>
    <button @click="deleteCar()">자동차 제거</button>
  </div>  
</template>

<script>
export default {
    data(){
        return {
            inputValue:'',            
            carList:this.$store.state.carList,
        }
    },
    methods:{
        addcar(){
            this.$store.commit('ADD_CAR',{name:this.inputValue});
        },
        deleteCar(){
            this.$store.commit('DELETE_CAR',this.inputValue);
        }
    },
    watch:{
        '$store.state.carList':{
            deep:true,
            handler(){
                this.carList=this.$store.state.carList
            }
        }
    }
}
</script>

3. actions

비동기 함수를 사용해야 할 경우 actions에 함수를 만들어 선언한다. 예를 들어 서버에서 가져온 데이터를 state에 선언 되어있는데 프로퍼티에 전달하여 사용할경우다.

store/index.js 파일에 서버로 부터 받을 함수인 getUserList() 선언 후 state의 userList에 값을 변경해야 하기 때문에 mutations 선언되어있는 ADD_USER_LIST 호출하기 위해 commit을 사용하여 전달 한다.

  • 첫 번째 파라미터는 context 이며 commit와 dispatch 함수를 사용할 수 있다.
  • 두 번째 파라미터는 다른 컴포넌트에서 전달 받을 object 및 프로퍼티 이다.
import Vue from 'vue';
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex);

export default new Vuex.Store({    
    state:{
        userList:[]
    },
    mutations:{
        ADD_USER_LIST(state,users){
            state.userList=users;            
        },                
    },
    // 비동기 로직 추가 시간이 오래 걸리는 작업(서버데이터 받기 , 타이머 등)
    actions:{
        getUserList(context,url){
            axios.get(url).then(res=>{     
                context.commit('ADD_USER_LIST',res.data);                
            });            
        }
    },    
});

store의 actions 선언되어있는 getUserList 호출하려면 dispatch를 사용하여 호출한다.

  • 첫 번째 파라미터는 actions 선언되어있는 함수 이름이다.
  • 두 번째 파라미터는 전달할 데이터 이다.
<template>
  <div>
    <div v-for="(user,index) in users" :key="index">
        <p>{{user.name}}</p>         
    </div>
  </div>  
</template>

<script>
export default {
    computed:{
        users(){
            return this.$store.state.userList;
        }
    },
    created(){
        this.getUserList();
    },
    data(){
        return{                        
            userUrl:'https://jsonplaceholder.typicode.com/users',
        }
    },
    methods:{
        getUserList(){
            this.$store.dispatch("getUserList",this.userUrl);            
        }
    }
}
</script>

4. getters

computed와 비슷하며 state 선언되어있는 데이터를 재 가공하여 다른 컴포넌트나 vue에서 사용한다.

getters에 재 가공할 함수를 선언 후 가공된 데이터를 return 한다.

import Vue from 'vue';
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex);

export default new Vuex.Store({    
    state:{
        userList:[]
    },
    mutations:{
        ADD_USER_LIST(state,users){
            state.userList=users;            
        },                
    },    
    actions:{
        getUserList(context,url){
            axios.get(url).then(res=>{     
                console.log(res.data);
                context.commit('ADD_USER_LIST',res.data);                
            });            
        }
    },
    getters:{
        getFilterName(state){
            return state.userList.filter(user=>{
                return user.name.includes('C');
            });
        }
    }
});

컴포넌트에서 computed에 store에 getters에 선언한 함수를 다음과 같이 사용가능
this.$store.getters.getFilterName

<template>
  <div>
    <div>
      <div v-for="user in filterList" :key="user.id">
        <p>{{user.name}}</p>         
        </div>
    </div>    
  </div>  
</template>

<script>
export default {
    computed:{        
        filterList(){
            return this.$store.getters.getFilterName;
        }
    },
    created(){
        this.getUserList();
    },
    data(){
        return{                        
            userUrl:'https://jsonplaceholder.typicode.com/users',
        }
    },
    methods:{
        getUserList(){
            this.$store.dispatch("getUserList",this.userUrl);            
        }
    }
}
</script>

store 모듈화

1. store 폴더아래 modules 폴더를 만든다.

2. 모듈 파일 만들기

모듈 파일을 다음과 같이 만들고 이름을 구분짓기 위해서 namespaced: true 추가해야 한다.

import axios from 'axios'

export default{
    namespaced: true,
    state:{
        userList:[],
        name:''
    },
    mutations:{
        ADD_USER_LIST(state,users){
            state.userList=users;            
        },                
        ADD_NAME(state,name){
            state.name=name;
        }
    },    
    actions:{
        getUserList(context,url){
            axios.get(url).then(res=>{     
                console.log(res.data);
                context.commit('ADD_USER_LIST',res.data);                
            });            
        }
    },
    getters:{
        getFilterName(state){
            return state.userList.filter(user=>{
                return user.name.includes('C');
            });
        }
    }
}

3. store 선언 되어있는 index.js에 다음과 같이 modules 프로퍼티에 2번에서 만든 파일을 추가한다.

import Vue from 'vue';
import Vuex from 'vuex'
import userListStore from '@/store/modules/userListStore.js'
Vue.use(Vuex);

export default new Vuex.Store({            
    modules:{        
        userListStore
    }
});

4. vue에서 사용하기

아래와 같이 모듈에 등록한 userListStore 네임스페이스를 이용하여 store 내용을 수정 가져온다.

this.$store.state.userListStore.userList;
this.$store.commit('userListStore/ADD_NAME','Jaewon');
this.$store.dispatch("userListStore/getUserList",this.userUrl);
this.$store.getters['userListStore/getFilterName'];

0개의 댓글