Study/Vue

Vue.js 시작하기 04. 컴포넌트 통신방식

going.yoon 2022. 1. 19. 20:27

뷰에서 컴포넌트 통신은 아래와 같은 구조를 가진다.

상위에서 하위로는 데이터를 내려주는 프롭스 속성,

하위에서 상위로는 이벤트를 올려주는 이벤트 발생

 

이러한 통신 규칙이 필요한 이유는, 기존의 MVC 패턴에서처럼 데이터가 N방향 통신을 하는 경우,

데이터의 영향이 컴포넌트 간에 복잡하게 영향을 미치기 때문에 데이터의 흐름을 추적하기 어렵기 때문이다.

 

뷰의 컴포넌트 통신규칙을 지킨다면 데이터의 흐름을 추적하기 쉽다!!

 

 

 

#Props(상위에서 하위컴포넌트로 전달되는 데이터)

아래의 예시를 통해서 컴포넌트간의 통신(상위 to 하위)가 어떻게 이루어지는지 보자.

첫번째로 Vue 인스턴스 생성 시 data 속성값을 설정해준다.

  new Vue({
            el : '#app',
            components : {
                'app-header' : appHeader
            },
            data : { //Vue 인스턴스에 이런식으로 data를 넣어줬을 때
                message: 'hi'
            }
        })

 

루트 컴포넌트에 메세지라는 이름의 데이터가 바인드되었다!

 

 

그러면 이 루트컴포넌트의 데이터를 하위 컴포넌트에서 받아오려면 어떻게 해야될까?

 

<body>
    <div id="app">
        <!--app-header v-bind:프롭스 속성 이름="상위컴포넌트의 데이터 이름"-->
        <app-header v-bind:propsdata="message"></app-header>
        <!-- app-header 내의 propsdata라는 값에다가 상위 컴포넌트의 data중 message라는 이름을 가진애를 넣어주겠다.-->
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var appHeader = {
            template : '<h1>header</h1>' ,
            props: ['propsdata']
        }

        new Vue({
            el : '#app',
            components : {
                'app-header' : appHeader
            },
            data : {
                message: 'hi'
            }
        })
    </script>
</body>

 

하위 컴포넌트에 props 변수를 선언해주고, 태그 내 v-bind 속성을 통해 해당 변수에 상위 컴포넌트의 데이터 변수명을 맵핑해준다.

그러면 하위 컴포넌트에서 해당 값을 가져올 수 있는데,

아까 선언해주었던 Root 컴포넌트의 message라는 데이터(hi)가, AppHeader 컴포넌트의 propsdata에 들어갔음을 확인할 수 있다.

 

 

#props의 속성

appHeader와 appContent에 똑같이 propsdata라고 정의를 해줘도 화면에서는 각각 message와 num값이 잘 출력된다.

<body>
    <div id="app">
        <app-header v-bind:propsdata="message"></app-header>
        <app-content v-bind:propsdata="num"></app-content>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var appHeader = {
            template : '<h1>{{propsdata}}</h1>' ,
            props: ['propsdata']
        }

        var appContent = {
            template : '<div>{{propsdata}}</div>',
            props : ['propsdata']
        }

        new Vue({
            el : '#app',
            components : {
                'app-header' : appHeader,
                'app-content' : appContent
            },
            data : {
                message: 'hi',
                num:10
            }
        })
    </script>
</body>

 

 

 

#event emit

 

 

<body>
    <div id="app">
       <app-header></app-header>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var appHeader = { //v-on click에서 passEvnet를 정의해주고, passEvent는 메소드에서 구현된다.
            template : '<button v-on:click="passEvent">click me</button>',
            methods: { //이벤트를 발행할 때 이름을 pass라고 하겠다.
                passEvent : function () {
                    this.$emit('pass');
                }
            }
        }
        new Vue({
            el : '#app',
            components : {
                'app-header' : appHeader
            }
        })
    </script>
</body>

그러면 이벤트 발행 이력을 조회해볼 수 있다.

 

 

 

#EventEmit으로 함수 실행해보기

<app-header v-on:하위컴포넌트에서 발생한 이벤트 이름="상위 컴포넌트의 메소드 이름"> 을 활용해서 상위 객체에서 이벤트 발생시 실행할 함수를 정의해줄 수 있다.

 

<body>
    <div id="app">
       <app-header v-on:pass="logText"></app-header>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var appHeader = { //v-on click에서 passEvnet를 정의해주고, passEvent는 메소드에서 구현된다.
            template : '<button v-on:click="passEvent">click me</button>',
            methods: { //이벤트를 발행할 때 이름을 pass라고 하겠다.
                passEvent : function () {
                    this.$emit('pass');
                }
            }
        }
        new Vue({
            el : '#app',
            components : {
                'app-header' : appHeader
            },
            methods : {
                logText : function(){
                    console.log('hi');
                }
            }
        })
    </script>
</body>

그러면 아래와 같이 버튼을 클릭했을 때 콘솔로그에 hi가 찍히는 것을 확인할 수 있다.

 

 

 

 

 

num을 하나 올려주는 이벤트를 가지는 루트 밑 컴포넌트 하나 더 추가(app-content)

<body>
    <div id="app">
        <p>{{num}}</p>
       <app-header v-on:pass="logText"></app-header>
       <app-content v-on:add="addNum"></app-content>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var appHeader = { //v-on click에서 passEvnet를 정의해주고, passEvent는 메소드에서 구현된다.
            template : '<button v-on:click="passEvent">click me</button>',
            methods: { //이벤트를 발행할 때 이름을 pass라고 하겠다.
                passEvent : function () {
                    this.$emit('pass');
                }
            }
        };

        var appContent = {
            template : '<button v-on:click="addNumer">click Me</button>',
            methods : {
                addNumer : function() {
                    this.$emit('add');
                }
            }
        };

        new Vue({
            el : '#app',
            components : {
                'app-header' : appHeader,
                'app-content' : appContent
            },
            methods : {
                logText : function(){
                    console.log('hi');
                },
                addNum : function(){
                    this.num = this.num +1;
                }
            } ,
            data : {
                num : 10
            }
        })
    </script>
</body>

 

 

두번째 clink me누르면 num이 계속 올라감

 

 

 

 

해당 포스팅은 인프런의 Vue.js 시작하기 - Age of Vue.js 학습 후 정리한 내용임을 알려드립니다.