IT 기술/[Vue] 기본
2. 뷰 컴포넌트 통신
Lee Hye Won
2021. 6. 1. 14:50
컴포넌트 간 통신과 유효범위
뷰는 여러 컴포넌트로 화면을 구성하는데, 각 컴포넌트의 유효 범위가 독립적이기 때문에 다른 컴포넌트의 값을 직접적으로 참조할 수 없다.
따라서 뷰 프레임워크 자체에서 정의한 데이터 전달 방법인 '상위(부모) - 하위(자식) 컴포넌트 간의 데이터 전달 방법'을 따라야 한다.
지역 혹은 전역 컴포넌트를 등록하면,
등록된 컴포넌트는 하위 컴포넌트가 되고
하위 컴포넌트를 등록한 인스턴스는 상위 컴포넌트가 된다.
상위 → 하위 : props 라는 속성을 전달
하위 → 상위 : 이벤트만 전달 가능
상위에서 하위 컴포넌트로 데이터 전달하기
// 상위 컴포넌트
<child-component v-bind:propsdata="message"></child-component>
...
// 하위 컴포넌트
// Vue.component() 이용하여 하위 컴포넌트인 child-cmoponent 를 등록
Vue.component('child-component', {
props: ['propsdata'], // props 속성으로 propsdata 를 정의
template: '<p>{{ propsdata }}</p>'
});
// new Vue 로 인스턴스 생성
new Vue({
el: '#app',
data: {
message: 'Hello! Vue'
}
});
→ 뷰 인스턴스의 data 속성에 정의된 message 속성을 하위 컴포넌트에 props 로 전달하여 화면에 출력
하위에서 상위 컴포넌트로 이벤트 전달하기
# 이벤트 발생과 수신 형식
// 이벤트 발생 (하위 컴포넌트의 특정 메서드에서 발생 → this 는 하위 컴포넌트를 가리킴)
this.$emit('이벤트명');
// 이벤트 수신
<child-component v-on:이벤트명="상위 컴포넌트의 메서드명"></child-component>
<div id="app">
<child-component v-on:show-log="printText"></child-component> // 3. show-log 의 대상 메서드인 최상위 컴포넌트의 메서드 printText() 실행
</div>
...
<script>
Vue.component('child-component', {
template: '<button v-on:click="showLog">show</button>', // 1. show 버튼 클릭 시 showLog() 메서드 실행
methods: {
showLog: function() {
this.$emit('show-log'); // 2. show-log 이벤트 발생
}
}
});
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue! passed from Parent Component'
},
methods: {
printText: function() {
console.log("received an event");
}
}
});
</script>
같은 레벨의 컴포넌트 간 통신
뷰는 상위에서 하위로만 데이터를 전달해야 하는 기본적인 통신 규칙을 따르기 때문에 바로 옆 컴포넌트에게 값을 전달하려면
하위에서 공통 상위 컴포넌트로 이벤트를 전달한 후 공통 상위 컴포넌트에서 2개의 하위 컴포넌트에 props 를 내려 보내야 한다.
하지만, 이런 통신 구조를 유지하다보면 상위 컴포넌트가 필요 없어도 그저 같은 레벨 간 통신을 위해 상위 컴포넌트를 두어야 한다.
이를 해결할 수 있는 방법이 이벤트 버스이다.
관계 없는 컴포넌트 간 통신 : 이벤트 버스
# 이벤트 버스 형식
- 보내는 컴포넌트에서는 .$emit()
- 받는 컴포넌트에서는 .$on()
// 이벤트 버스 위한 추가 인스턴스 1개 생성 (애플리케이션 로직을 담는 인스턴스와는 별개)
var eventBus = new Vue();
// 이벤트 보내는 컴포넌트
methods: {
메서드명: function() {
eventBus.$emit('이벤트명', 데이터);
}
}
// 이벤트를 받는 컴포넌트
methods: {
created: function() {
eventBus.$on('이벤트명', function(데이터) {
...
});
}
}
# 이벤트 버스 구현 예시
<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); // triggerEventBus 발생하는 로직 추가. 발생할 때 수신하는 쪽에 인자 값으로 100 이라는 숫자를 함께 전달
}
}
});
var app = new Vue({
el: '#app',
created: function() {
eventBus.$on('triggerEventBus', function(value) { // 이벤트를 받는 로직.
console.log('이벤트를 전달받음. 전달받은 값 : ", value);
});
}
});
</script>