본문 바로가기

클라이언트/Vue.js
[뷰(Vue)] export, import / 컴포넌트

// export, import

- export : 내보내기 /  import : 불러오기
    > js 파일에서 내보내는 데이터를 vue 파일에서 import해서 사용 가능하다.

export default grape

export {grape1, grape2}

 

import grape from './assets/room.js';

import {grape1, grape2} from './assets/room.js';

<div v-for="(a,i) in rooms" :key="i">
    <img :src="a.image" class="images">
    <h4>{{ a.title }}</h4>
    <p>{{ a.price }}원</p>
</div>

// 컴포넌트(Component)

- vue 파일을 따로 생성해서 코드를 축약시켜 준다.

<template>
  HTML 코드
</template>

<script>
export default {
  name : '',
}
</script>

<style>
</style>


- .vue 파일을 import 한 후 component로 등록한다.

import 변수명 from '경로'

export default {
  data() {
  },
  components : {
    변수명,
  }
}


- 등록한 component는 자유롭게 태그로 사용할 수 있다.

<component명>
</component명>


** 컴포넌트명은 2단어 이상이어야 한다!! 한 단어도 가능하게 하려면 package.json의 rues에 아래 설정을 추가한다.

"vue/multi-word-component-names": "off"


- 전역 컴포넌트

//전역 컴포넌트
Vue.component('app-content', {
   template: '<div>Vue 공부 중입니당</div>'
});

//지역 컴포넌트
new Vue({
    el: '#app',
    //지역 컴포넌트
    components: {
        'app-footer' : {
            template: '<footer>footer</footer>'
        }
    }
});

// props

- 상위 컴포넌트의 데이터를 하위 컴포넌트에서 바로 데이터바인딩할 수 없고, 다른 방법이 필요하다.

1. 상위 컴포넌트에서 하위 컴포넌트로 보내기

<컴포넌트명 :데이터명="보낼 데이터명"/>


2. 하위 컴포넌트에서 데이터 불러오기

props : {
    데이터명 : 자료형
}


3. 하위 컴포넌트에서 데이터 사용하기


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
<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>
</html>

// custom event

- 하위 컴포넌트에서 상위 컴포넌트의 데이터를 변경하기 위해 사용한다.

1. 하위 컴포넌트에서 상위 컴포넌트로 메시지를 보낸다.
- $emit() 이용

<h4 @click="$emit('openModal', a.id); $emit('report')" class="titleModal">{{ a.title }}</h4>


2. 상위 컴포넌트에서 하위 컴포넌트가 전송한 메시지를 수신하여 데이터를 변경한다.
- @이용하여 메시지 수신

<CardRoom :rooms="rooms" :isOpened="isOpened" @openModal="isOpened = true; clicked= $event" @report="clicked++"/>


// 하위 컴포넌트 간의 통신

1. 하위 컴포넌트1에서 상위 컴포넌트로 전달 > 상위 컴포넌트에서 하위 컴포넌트2로 전달
2. 이벤트 버스 활용 
    - 보내는 컴포넌트 : .$emit()
    - 받는 컴포넌트 : .$on()

//이벤트 버스를 위한 추가 인스턴스 1개 생성
var eventBus = new Vue();

// 이벤트를 보내는 컴포넌트
methods: {
	메소드명 : function() {
    	eventBus.$emit('이벤트명', '데이터');
    }
}

//이벤트를 받는 컴포넌트
methods: {
	created: function() {
	    eventBus.$on('이벤트명', function(데이터) {
    });
}

1. 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
<body>

    <div id="app">
        <app-header v-bind:propsdata1="num1" v-bind:propsdata2="num2"></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: '<h1>{{ propsdata1 }}, {{ propsdata2 }}</h1>',
            props: ['propsdata1','propsdata2']
        }
    
        var appContent = {
            template: '<div>content <button v-on:click="passNum">pass</button></div>',
            methods: {
                passNum: function() {
                    this.$emit('pass', 10, 15);
                }
            }
        }

        new Vue({
            el: '#app',
            components: {
                'app-header': appHeader,
                'app-content': appContent
            },
            data: {
                num1: 0,
                num2: 0
            },
            methods: {
                deliverNum: function(val1, val2) {
                    this.num1 = val1;
                    this.num2 = val2;
                }
            }
        })

    </script>

</body>
</html>

2.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
<body>

    <div id="app">
        <child-component></child-component>
    </div>     

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>

        var eventBus = new Vue();
        Vue.component('child-component', {
            template: '<div>하위 컴포넌트 영역입니다.<button v-on:click="showLog">show</button></div>',
            methods: {
                showLog: function() {
                    eventBus.$emit('triggerEventBus', 100);
                }
            }
        });

        var app = new Vue({
            el: '#app',
            created: function() {
                eventBus.$on('triggerEventBus', function(value) {
                    console.log("이벤트를 전달 받음. 전달받은 값: ", value);
                });
            }    
        });
    
    </script>

</body>
</html>

// slot

- 상위 컴포넌트에서 하위 컴포넌트로 데이터를 간편하게 보내고 사용할 수 있다.

1. 상위 컴포넌트에서 하위 컴포넌트로 데이터 전송

<하위 컴포넌트>보낼 데이터</하위컴포넌트>


2. 하위 컴포넌트에서 데이터 사용

<slot></slot>

 

- name속성으로 이름을 지어주고 slot을 여러 개 사용할 수 있다.

<v-slot:이름>데이터</template>

<slot name="이름"></slot>