반응형

컴포넌트의 데이터는 각 컴포넌트에서 관리하기 때문에 각 컴포넌트는 고유한 데이터 유효범위를 갖는다.

따라서 컴포넌트간 데이터를 주고 받기 위해서는 특별한 규칙을 따라야한다.

 

 

위와 같이 상→하로 props를 통해 데이터를 전달하고

하→상은 이벤트를 올려서 전달한다.

 

*컴포넌트 통신 규칙 : 직접 연관이 되어있는 상, 하위 컴포넌트 간의 데이터 전달이 가능하다. (데이터 오류 발생시 추적에 용이)

 

 

1. props (상 -> 하)

props는 위에서 설명한 것과 같이 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달하는 방법이다.

 

부모 컴포넌트에 등록되어 있는 데이터를 가져오는 기본적인 사용 방법은 

 

1. 자식(하위) 컴포넌트에 props 속성을 사용해 프롭스 속성명을 등록해준다.

var appHeader = {
    template: '<h1>Title</h1>',
    props: ['propsdata']    // 프롭스 속성 명은 임의로 지정이 가능하다.
}
 
new Vue({
    el: '#app',
    component: {
        'app-header' : appHeader,
    },
    data: {
        message: 'hi',
    }
})

 

2. 자식 컴포넌트에서 v-bind를 사용해서 상위 컴포넌트의 데이터 속성을 해당하는 자식 컴포넌트로 전달한다. 

<!-- v-bind:프롭스 명="상위 컴포넌트의 data 속성" -->
<app-header v-bind:propsdata="message"></app-header>

 

크게 위 1, 2번의 방법으로 적용할 수 있다.

 

<div id="app">
    <app-header v-bind:propsdata="message"></app-header>
    <app-content v-bind:propsnum="num"></app-content>
</div>
 
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    var appHeader = {
        template: '<h1>{{ propsdata }}</h1>',   // {{ 데이터 }} 이중 괄호를 통해 부모 컴포넌트로부터 받은 props 값을 그대로 뿌려줄 수 있다.
        props: ['propsdata'],
    }
    var appContent = {
        // 각 영역 안에 데이터는 고유의 데이터로 가진다. 따라서 appHeader와 마찬가지로 propsdata라는 같은 이름으로 사용해도 된다.
        template: '<div>{{ propsnum }}</div>',
        props: ['propsnum'],
    }
    new Vue({
        el: '#app',
        components: {
            'app-header' : appHeader,
            'app-content' : appContent,
        },
        data: {
            message: 'hi',
            num: 10
        }
    });
</script>

 

 

2. Event Emit (하 -> 상)

부모 컴포넌트의 데이터를 가져올 때 props 속성을 사용한다면

자식 컴포넌트에서는 이벤트 발생(emit)을 통해 상위로 이벤트를 전달해준다.

 

방법은

1. 자식 컴포넌트에 event emit 메소드를 등록해준다.

// appHeader에 있는 button을 클릭하면 passEvent 함수가 실행되고 그 함수는 'pass'라는 이벤트명을 가진 event emit용 함수이다.
var appHeader = {
    template: '<button v-on:click="passEvent">click me</button>',
    methods: {
        passEvent: function(){  //passEvent라는 메소드를 통해 해당 자식 컴포넌트에 $emit 이벤트명은 정의한다.
            this.$emit('pass'); // 이벤트 이름 등록 : $emit('이벤트명')
        }
    }
}
 
new Vue({
    el: '#app',
    components: {
        'app-header': appHeader,
    },
    methods: {
        logText: function(){
            console.log('hi');
        },
    }
})

 

2. 자식 컴포넌트에 $emit으로 등록한 이벤트 명을 통해 부모 컴포넌트의 메소드를 가져온다.

<!-- v:on:하위 컴포넌트에서 발생한 이벤트 이름="상위 컴포넌트의 메소드 이름" -->
<app-header v-on:pass="logText"></app-header>

 

위와 같이 작업하면 app-header 영역에 버튼이 생기고

해당 버튼을 클릭하면 자식 요소의 버튼을 클릭하지만 부모 요소에 logText() 메소드가 실행된다.

<div id="app">
    <!-- v:on:하위 컴포넌트에서 발생한 이벤트 이름="상위 컴포넌트의 메소드 이름" -->
    <app-header v-on:pass="logText"></app-header>
    <app-content v-on:number="addNum"></app-content>
</div>
 
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    var appHeader = {
        template: '<button v-on:click="passEvent">click me</button>',
        methods: {
            passEvent: function(){
                this.$emit('pass');
            }
        }
    }
    var appContent = {
        template: '<button v-on:click="addNumber">add</button>',
        methods: {
            addNumber: function(){
                this.$emit('number');
            }
        }
    }
    new Vue({
        el: '#app',
        components: {
            'app-header': appHeader,
            'app-content': appContent,
        },
        methods: {
            logText: function(){
                console.log('hi');
            },
            addNum: function(){
                this.num++
                console.log(this.num);
            }
        },
        data: {
            num: 10,
        }
    })
</script>

 

위와 같은 소스로 자식 컴포넌트에서의 이벤트로 부모 컴포넌트의 data 값을 변경할 수도 있다.

 

3. 같은 레벨에서의 컴포넌트 통신 방법

같은 레벨의 컴포넌트에서는 다이렉트로 데이터를 통신할 수 없고 연결되어 있는 부모 컴포넌트를 통해서 데이터를 주고받을 수 있다.

 

AppContent에서 버튼을 클릭해서 10이라는 숫자를 AppHeader로 보내기 위해서는 다음과 같이 적용할 수 있다.

 

1. AppContent에서 Root 컴포넌트로 event emit을 이용해서 이벤트를 전달한다.

<div id="app">
    <app-header></app-header>
    <app-content v-on:pass="deliverNum"></app-content>
</div>
 
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    var appHeader = {
        template: '<div>header</div>',
    }
    var appContent = {
        template: '<div>Content <button v-on:click="passNum">pass</button></div>',
        methods: {
            passNum: function(){
                this.$emit('pass', 10); // 10이라는 숫자를 pass 이벤트에 담아 보낸다.
            },
        }
    }
    new Vue({
        el: '#app',
        components: {
            'app-header' : appHeader,
            'app-content' : appContent,
        },
        data: {
            num: 0,
        },
        methods: {
            deliverNum: function(value){    // value는 $emit으로 보낸 10이 담겨온다.
                this.num = value;
            }
        }
    });
</script>

 

2. 부모 컴포넌트에서 AppContent로부터 받아온 이벤트를 AppHeader로 props를 통해 전달한다.

<div id="app">
    <app-header v-bind:propsdata="num"></app-header>
    <app-content v-on:pass="deliverNum"></app-content>
</div>
 
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    var appHeader = {
        template: '<div>header</div>',
        props: ['propsdata']    // props 등록
    }
    var appContent = {
        template: '<div>Content <button v-on:click="passNum">pass</button></div>',
        methods: {
            passNum: function(){
                this.$emit('pass', 10);
            },
        }
    }
    new Vue({
        el: '#app',
        components: {
            'app-header' : appHeader,
            'app-content' : appContent,
        },
        data: {
            num: 0,
        },
        methods: {
            deliverNum: function(value){
                this.num = value;
            }
        }
    });
</script>

 

위 처럼 작업하게 되면 AppContent에 있는 버튼을 클릭할 때 

AppHeader에 propsdata:10 값이 전달된다.

 

 

 


참고

인프런 'Vue.js 시작하기 - Age of Vue.js' 강좌

 

 

 

반응형

'Frontend > Vue.js' 카테고리의 다른 글

[vue 2 기초] Axios (액시오스)  (0) 2023.11.07
[vue 2 기초] 라우터  (1) 2023.11.06
[Vue 2 기초] 컴포넌트  (0) 2023.11.03
[Vue 2 기초] 인스턴스  (0) 2023.11.03
Vue.js 란?  (0) 2023.11.03

+ Recent posts