내가 한 노력들

[ Vue ] 형제 컴포넌트간의 통신하는 방법 본문

IT 공부/Vue

[ Vue ] 형제 컴포넌트간의 통신하는 방법

JONGI-N CHOI 2022. 12. 1. 13:00

Vuex를 사용하여, 컴포넌트간의 통신을 쉽게 할 수 있습니다

vuex는 컴포넌트간 공통적인 상태관리 라이브러리입니다. 

컴포넌트간에 데이터를 주고 받고, 통신하기 위해서는 props와 emit등을 사용하는데 컴포넌트의 관계가 복잡하게 되면 의미없는 props가 반복되거나 구현하기 힘든 경우가 있습니다. 

 

그런 경우에 vuex를 이용하면, 쉽게 컴포넌트간 공통 데이터 관리를 할 수 있습니다. 


vuex파일 설정 

import { createStore } from 'vuex'

export default createStore({  

    state: {
    	is_clicked: false,
    },
    mutations: {
        changeClickedState(state) {
            state.is_clicked = true;
        },
    },
    actions: {
    	clickBtn(context) {
            context.commit('changeClickedState');
        },
    },
    getters: {
        is_clicked(state) {
            return state.is_clicked;
        }
    },
});

간단하게 위의 코드를 설명하면, 데이터의 상태값이 state 속성에 정의되고, 

state 데이터의 값을 가져오기 위해서는 직접적으로 가져오면 안되고, getters를 이용해서 리턴 받아야합니다.

 

또한, state의 데이터는 직접적으로 수정이되면 안되기 때문에 mutations 속성에 따로 함수를 정의해서, 변경을 하도록 합니다. 

actions에서는 보통 비동기 처리를 담당하게 됩니다. 

 

데이터를 직접적으로 변경하는 부분은 mutation이지만 (동기처리), vue 컴포넌트에서 값을 변경하기 위해서는 action을 통해서 commit을 통한 데이터 변경이 원칙입니다. 

 

물론, 컴포넌트에서 즉시 commit을 통해서 데이터를 변경하는 것이 안되는 것은 아니지만, action을 통해 commit하도록 합니다. 

 

컴포넌트에서 clickBtn 함수를 실행하면, commit을 통해 mutaionsd의 changeClickedState 함수가 실행이되어, state의 is_clicked 속성의 값이 false에서 ture로 바뀌게 되는 코드입니다. 


vue 컴포넌트 ( 형제 1 )

<template>
    <div>
        <button @click="$store.dispatch('clickBtn')">이벤트 발생</button>
    </div>
</template>

위의 코드는 vue 컴포넌트를 간략하게 표현한 코드인데, 간단하게 설명하자면 

@click 은 v-on:click 의 축약형이라고 생각하시면 됩니다. 

$store.dispatch('clickBtn')에서 $store은 vuex의 인스턴스입니다. vue 에서 내장 속성에 접근하는 경우에는 "$"를 붙히게 됩니다.

(예를 들어, router를 사용하는 경우에는 $router.push({name: 'index'}) )

dispatch 메소드를 통해 actions에 정의된 메소드를 사용할 수 있습니다. 

 

요약하면, "버튼 클릭시에 vuex의 actions 속성에 정의된 clickBtn함수를 실행해라" 입니다. 

 

또한, 위의 코드는 간략하게 표현하기 위해서 태그안에 인라인으로 코드를 작성했기 때문에 "this"가 생략되어 있지만, 보통 methods: {} 안에서 사용하는 경우는 this.$store로 사용해야 합니다. 


vue 컴포넌트 (형제 2)

<template>
    <div>{{ text }}</div>
</template>

<script>
export default {
    components: {},
    data () {
        return {
            text: '',
        }
    },
    computed: {
        is_clicked() {
            return this.$store.getters['is_clicked'];
        }
    },
    watch: {
        is_clicked() {
            this.clickBtn();
        }
    },
    methods: {
        clickBtn() {
            this.text = "clicked!!";
        }
    }
}
</script>

위의 컴포넌트에서는 우선 computed를 통해서 vuex로 부터 is_clicked의 데이터를 받아옵니다. 

그리고, watch를 이용해서 is_clicked 값이 변경되나 감시를 하고, 변경이 일어나게 되면 clickedBtn 메소드를 실행시켜, text의 값에 "clicked!!" 가 들어가, 화면에 표시 되게 됩니다. 

 

따라서, 컴포넌트 (형제 2)에서는 vuex로 부터 is_clicked (= false)값을 받아와서 감시를 하고 있고, 컴포넌트 (형제 1)에서 버튼을 클릭해 vuex의 is_clicked의 값을 true로 변경하게 되면, 컴포넌트 (형제 2)의 watch에서 clickBtn 메소드를 실행시키는 구조입니다. 

 


위와같이 vuex를 이용하게 되면, 형제 컴포넌트 뿐만 아니라 모든 컴포넌트 위치에서도 쉽게 통신이 가능하게 됩니다. 

물론, 통신의 방법은 vuex만이 있는게 아니며 단순히 emit과 props만으로도 구현이 가능하고 eventbus라 던가 mitt 라이브러리를 통한 방법도 있습니다. 

 

하지만, 프로젝트가 커지고 관계가 복잡한 경우에 가장 쉽고 활용하기 좋은 방법은 vuex라고 생각합니다.