[Vue.js] Vue 컴포넌트간의 통신!
- 웹 개발/Vue.js
- 2019. 9. 15. 02:44
컴포넌트간 통신
- 뷰의 경우는 컴포넌트로 화면을 구성하기 때문에 같은 웹페이지라도 데이터를 공유할 수 없는 경우가 많다.
- 각 컴포넌트들의 scope(유효범위)가 독립적이기 때문에 다른 컴포넌트의 값을 직접적으로 참조할 수가 없다.
상/하위 컴포넌트 관계
- 뷰의 가장 기본적인 데이터 전달방법.
- 상위(Parent) 컴포넌트에서 props라는 속성으로 전달.
- props : 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달할 때 사용하는 속성. 하위 컴포넌트의 속성에 정의.
Vue.component('child-component',{
props:['props 속성 이름'],
});
- 상위 컴포넌트의 HTML 코드에 정의된 child-component 태그에 v-bind 속성을 정의.
<child-component v-bind:props속성명="상위 컴포넌트의 data속성"></child-component>
예제로 확인
- 뷰인스턴스 자체가 상위 컴포넌트가 됨.
<!DOCTYPE html>
<html lang="ko" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
<div id="app">
<child-component v-bind:propsdataa="message"></child-component>
</div>
<script>
Vue.component('child-component',{
props:['propsdataa'],
template:'<p>{{propsdataa}}</p>'
});
new Vue({
el:'#app',
data:{
message:'Hello Vue! passed from Parent Component'
}
});
</script>
</body>
</html>
- 상위 컴포넌트의 message 속성을 하위 컴포넌트에 props로 데이터를 전달하여 메시지를 출력하는 코드.
- v-bind 속성에는 자식컴포넌트의 props 속성명을 쓰고 = 다음 ""(따옴표)안에 상위 컴포넌트로부터 받을 속성명을 기재.
- child-component는 상위 컴포넌트의 message를 받는 태그이므로 message에 있는 문자열 자체가 <child-component> 태그가 됨.
하위에서 상위로 컴포넌트 전달하기
- 이벤트를 발생시켜 상위 컴포넌트에 신호를 보냄.
- 상위 컴포넌트에서 하위 컴포넌트의 특정 이벤트가 발생하기를 기다리다가 이벤트가 발생하면 상위 컴포넌트에서 이벤트를 수신하여 상위 컴포넌트의 메서드를 호출하는 방식!.... 어렵다...
- 이벤트 발생은 $emit() / 수신은 v-on 속성을 이용합니다.
//이벤트 발생
this.$emit('이벤트명');
//이벤트 수신
<child-component v-on:이벤트명="상위 컴포넌트의 메소드명"></child-component>
- $emit()을 호출하면 괄호안에 정의된 이벤트가 발생됨. 주로 하위컴포넌트의 특정 메서드 내부에서 호출.(데이터를 상위에 전달하기 위해)
- 호출한 이벤트를 v-on 속성으로 받음. 호출될 상위 메소드명 지정.
이벤트 발생시키고 수신하기 예제로 보기
<!DOCTYPE html>
<html lang="ko" dir="ltr">
<head>
<meta charset="utf-8">
<title>sss</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
<div id="app">
<child-component v-on:show-log="printText"></child-component>
</div>
<script type="text/javascript">
Vue.component('child-component',{
template:'<button v-on:click="showLog">show</button>',
methods:{
showLog:function(){
this.$emit('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>
</body>
</html>
- 가장먼저 브라우저로 코드를 실행했을 때 show라는 버튼이 보일 것.
- 버튼을 누르면 click 이벤트가 발생되고(버튼은 click 이벤트만 바라보고 있음), 자신의 methods 속성에 있는 showLog에 정의된 함수를 실행하게됨.
- showLog 함수는 show-log 이벤트를 발생시키는데 이는 <child-component> 태그가 기다리고 있는 이벤트임
- 그래서 상위 컴포넌트인 뷰인스턴스에 정의된 printText 메소드를 실행해서 "received an event"라는 콘솔 메시지가 출력되는 것을 볼 수 있음.
같은 레벨의 컴포넌트 간의 통신
- A에서 B로 전달하려면 상위 컴포넌트에 이벤트로 값을 전달하고 하위 컴포넌트에 props를 내려보내야함.
- 다른 컴포넌트의 값을 직접 참조할 수는 없음!!
- 그러나! 이벤트 버스라는 방법으로 통신이 가능함.
이벤트 버스
- 개발자가 2개의 컴포넌트 간에 데이터를 주고받을 수 있는 방법.
- 이렇게 바로 전달할 수 있음.
- 이벤트 버스에 해당하는 인스턴스를 생성.
// 이벤트 버스를 위한 추가 인스턴스 1개 생성
var eventBus = new Vue();
- 보내는 컴포넌트에 $emit() / 받는 컴포넌트에 $on() 각각 정의해놓는다.
// 이벤트를 보내는 컴포넌트
methods:{
methodName : function(){
eventBus.$emit('eventName',"abc");
}
}
//이벤트를 받는 컴포넌트
methods:{
created:function(){
eventBus.$on('eventName',function(data){
console.log(data); //abc
});
}
}
구현 소스 보기
<!DOCTYPE html>
<html lang="ko" dir="ltr">
<head>
<meta charset="utf-8">
<title>ff</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
<div id="app">
<child-component></child-component>
</div>
<script type="text/javascript">
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>
- 이벤트 버스 인스턴스를 하나 생성.
- show라는 버튼이 있는데 클릭하면 하위 컴포넌트의 showLog 함수가 실행되면서 'triggerEventBus'라는 이벤트와 100이라는 값이 파라미터로 넘어가게됨.
- 뷰 인스턴스에서는 'triggerEventBus' 이벤트를 수신하여 value 변수로 100값을 할당받고 출력하면
- 이벤트를 전달받음. 전달받은 값: 100 <<< 출력결과.
장점 / 단점
- 이렇게 이벤트버스를 활용하면 props 속성을 이용하지 않고도 원하는 컴포넌트간에 직접적으로 데이터를 전달할 수 있어편리함.
- 하지만 컴포넌트가 많아지면 어디서 어디로 보냈는지 관리가 되지않는 문제 발생 -> 이를 해결하기 위해서 뷰엑스라는 상태관리도구가 필요함.
'웹 개발 > Vue.js' 카테고리의 다른 글
[Vue.js] ESLint 화면 에러 오버레이 처리하기 (0) | 2020.05.29 |
---|---|
[Vue.js] 뷰 인스턴스에서의 this 키워드(data) (0) | 2020.03.07 |
[Vue.js] 뷰 모델의 Reactivity 구현(Databinding에 관하여) (0) | 2020.03.04 |
[Vue.js] Vue 컴포넌트와 인스턴스 (0) | 2019.09.15 |
[Vue.js] 뷰 초 기본예제 Hello World 찍기, Vue.js Life Cycle 예제 (0) | 2019.09.12 |