Vue.component('컴포넌트 이름', {
// 컴포넌트 내용
}
new Vue({
components: {
'컴포넌트 이름': 컴포넌트 내용
}
})
두 번째 인스턴스에는 로컬 컴포넌트가 등록되지 않았으므로 오류가 표시 된다.
<html>
<head>
<title>인스턴스 유효 범위와 지역 컴포넌트, 전역 컴포넌트 간 관계 확인 예제</title>
</head>
<body>
<div id="app">
<h3>첫 번째 인스턴스 영역</h3>
<my-global-component></my-global-component>
<my-local-component></my-local-component>
</div>
<hr>
<div id="app2">
<h3>두 번째 인스턴스 영역</h3>
<my-global-component></my-global-component>
<my-local-component></my-local-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
<script>
// 전역 컴포넌트
Vue.component('my-global-component', {
template: '<div>전역 컴포넌트 입니다.</div>'
});
// 지역 컴포넌트
var cmp = {
template: '<div>지역 컴포넌트 입니다.</div>'
};
// 첫 번째 인스턴스
new Vue({
el: '#app'
components: {
'my-local-component': cmp
}
});
// 두 번째 인스턴스
new Vue({
el: '#app2'
});
</script>
</body>
</html>
상위-하위 컴포넌트 간에 데이터를 전달하는 기본 구조는 다음과 같다.
Vue.component('child-component', {
props: ['props 속성 이름'],
}
<child-component v-bind:props 속성 이름="상위 컴포넌트의 data 속성">
props는 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달할 때 사용하는 속성이다.
1) 하위 컴포넌트를 등록할 때 props 속성으로 하위 컴포넌트에서 사용할 속성을 지정한다.
2) child-component 태그에서 v-bind 속성의 왼쪽 값으로 1)에서 지정한 속성을 지정하고, 오른쪽 값으로 전달할 상위 컴포넌트의 data 속성을 지정한다.
<html>
<head>
<title>상위에서 하위 컴포넌트로 데이터 전달 예제</title>
</head>
<body>
<div id="app">
<!-- 팁: 오른쪽에서 왼쪽으로 속성을 읽으면 수월 함 -->
<child-component v-bind:propsdata="message"></child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
<script>
Vue.component('child-component', {
props: ['propsdata'],
template: '<p>{{ propsdata }}</p>'
});
// 인스턴스
new Vue({
el: '#app'
data: {
message: 'Hello Vue! passed from Parent Component'
}
});
</script>
</body>
</html>
Vue는 앵귤러의 양방향 데이터 바인딩과 리액트의 단방향 데이터 흐름의 장점을 결합한 프레임워크로, 상위 컴포넌트에서 하위 컴포넌트 한 방향으로만 데이터를 전달 하도록 구조화 되어 있기 때문에 하위에서 상위 컴포넌트로 데이터를 전달할 수 없다.
하위 컴포넌트에서 상위 컴포넌트로의 통신은 이벤트를 발생시켜(event emit) 상위 컴포넌트에 신호를 보내면 된다. 상위 컴포넌트는 하위 컴포넌트의 특정 이벤트를 수신하여 상위 컴포넌트의 메서드를 호출하는 것이다.
이벤트 발생과 수신은 $emit()과 v-on 속성을 사용하여 구현한다.
// 이벤트 발생
this.$emit('이벤트명');
$emit를 호출하면 괄호 안에 정의 된 이벤트가 발생한다. 그리고 일반적으로 $emit()을 호출하는 위치는 하위 컴포넌트의 특정 메서드 내부이다. 따라서 $emit()을 호출할 때 사용하는 this는 하위 컴포넌트를 가리킨다.
// 이벤트 수신
<child-component v-on:이벤트명="상위 컴포넌트의 메서드명">
<html>
<head>
<title>하위-상위 컴포넌트간 이벤트 발생 및 수신 예제</title>
</head>
<body>
<div id="app">
<child-component v-on:show-log="printText"></child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
<script>
Vue.component('child-component', {
template: '<button v-on:click="showLog">show</button>',
methods: {
showLog: function() {
this.$emit('show-log');
}
}
});
// 인스턴스
new Vue({
el: '#app'
data: {
message: 'Hello Vue! passed from Parent Component'
},
methods: {
printText: function() {
console.log('received an event');
}
}
});
</script>
</body>
</html>
이벤트 버스는 컴포넌트간 상위-하위 구조를 유지하지 않아도 개발자가 지정한 2개의 컴포넌트 간에 데이터를 주고받을 수 있는 방법이다.
이벤트 버스를 활용하면 props 속성을 이용하지 않아도 원하는 컴포넌트 간에 직접적으로 데이터를 전달할 수 있어서 편리하지만 컴포넌트가 많아지면 어디서 어디로 보냈는지 관리가 되지 않는 문제가 발생한다. 이 문제를 해결하려면 Vuex라는 상태 관리 도구가 필요하다.
// 이벤트 버스를 위한 추가 인스턴스 1개 생성
var eventBus = new Vue();
// 이벤트를 보내는 컴포넌트
methods: {
메서드명: function() {
eventBus.$emit('이벤트명', '데이터');
}
}
// 이벤트를 받는 컴포넌트
methods: {
created: function() {
eventBus.$on('이벤트명', function(데이터) {
...
});
}
}
이벤트 버스를 구현하려면 로직을 담는 인스턴스와는 별개로 새로운 인스턴스를 1개 생성하고,
생성한 인스턴스를 이용하여 이벤트를 보내고 받는다.
보내는 컴포넌트에서는 .$emit()을, 받는 컴포넌트에서는 .$on을 구현한다.
<html>
<head>
<title>이벤트 버스 예제</title>
</head>
<body>
<div id="app">
<child-component></child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
<script>
var eventBus = new Vue();
Vue.component('child-component', {
template: '<div>하위 컴포넌트 영역입니다.<button v-on:click="showLog">show</button>',
methods: {
showLog: function() {
eventBus.$emit('triggerEventBus', 100);
}
}
});
// 인스턴스
new Vue({
el: '#app'
created: function() {
eventBus.$on('triggerEventBus', function(value) {
console.log("이벤트를 전달받음. 전달받은 값 : ", value);
});
},
});
</script>
</body>
</html>