Vue의 경우 컴포넌트로 화면을 구성하므로 같은 웹 페이지라도 데이터를 공유할 수 없음
그 이유는 컴포넌트마다 자체적으로 고유한 유효 범위(Scope) 를 갖기 때문
각 컴포넌트의 유효 범위가 독립적이기 때문에 다른 컴포넌트의 값을 직접적으로 참조할 수가 없음
상 하위 컴포넌트 관계
직접 다른 컴포넌트의 값을 참조할 수 없기 때문에, 뷰 프레임워크 자체에서 정의한 컴포넌트 데이터 전달 방법을 따라야 한다.
기본적인 데이터 전달 방법은 바로 상위(부모) - 하위(자식) 컴포넌트 간의 데이터 전달 방법
하위 컴포넌트 — 이벤트발생 —> 상위 컴포넌트
상위 컴포넌트 — props 전달 —> 하위 컴포넌트
하위에서 상위는 기본적으로 이벤트만 전달할 수 있음
상위에서 하위 컴포넌트로 데이터 전달하기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<child-component v-bind:propsdata="message"></child-component>
</div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<script>
Vue.component("child-component", {
props : ["propsdata"],
template : "<p>{{propsdata}}</p>"
});
new Vue({
el : "#app",
data : {
message : "Hello World!!! This is parent message!! passed from Parent Component"
}
})
</script>
</html>
상위컴포넌트에서 하위컴포넌트로 데이터를 전달할 때는 props를 통해 전달한다.
- new Vue() 인스턴스 생성
- Vue.component()이용하여 하위 컴포넌트인 child-component등록
- child-component의 내용에 props 속성으로 propsdata 정의
- 하위 컴포넌트 태그
<child-component>
태그의 v-bind속성을 주어 v-bind:propsdata="message" 상위 컴포넌트의 message 속성값을 전달 - child-component의 template 속성에 정의된
<p>{{propsdata}}</p>
는 "Hello World!!! This is parent message!! passed from Parent Component" 로 변경
하위에서 상위 컴포넌트로 이벤트 전달하기
이벤트 발생과 수신
이벤트를 발생시켜(event emit) 상위 컴포넌트에 신호를 보내면, 상위 컴포넌트에서는 하위 컴포넌트의 특정 이벤트가 발생하기를 기다리고 있다가 하위 컴포넌트에서 특정 이벤트가 발생하면 상위 컴포넌트에서 해당 이벤트를 수신하여 데이터를 처리
이벤트 발생과 수신 형식
- 발생 : $emit()
- 수신 : v-on
// 이벤트 발생
this.$emit("이벤트명");
// 이벤트 수신
<child-component v-on:이벤트명="상위 컴포넌트 메서드명"></child-component>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<child-component v-on:show-log="printText"></child-component>
</div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<script>
Vue.component("child-component", {
template : "<button v-on:click='showLog'>show</button>",
methods : {
showLog : function(){
this.$emit("show-log", "parameter"); // 이벤트 발생
}
}
});
var app = new Vue({
el : "#app",
data : {
message : "Hello Vue! passed from Parent Component"
},
methods : {
printText : function(param){
console.log(param);
}
}
})
</script>
</html>
button을 클릭하면,
- 상위 컴포넌트로 show-log 이벤트를 발생시키면서 parameter문자열을 전송
- 상위 컴포넌트에서는 하위 컴포넌트에서 받은 parameter를 console.log로 출력
관계 없는 컴포넌트 간 통신 - 이벤트 버스
뷰는 상위에서 하위로만 데이터를 전달해야 하는 기본적인 통신 규칙을 따르기 때문에 바로 옆 컴포넌트에 값을 전달하려면 하위에서 공통 상위 컴포넌트로 이벤트를 전달한 후 공통 상위 컴포넌트에서 2개의 하위 컴포넌트에 props를 내려 보내야 한다.
⇒ 즉, 상위 컴포넌트가 필요 없음에도 같은 레벨 간에 통신하기 위해 강제로 상위 컴포넌트를 두어야한다는 말이다.
이를 해결하기 위한 방법이 이벤트버스를 이용하는 것이다.
이벤트 버스를 이용하면 이런 상위 - 하위 관계를 유지하고 있지 않아도 데이터를 한 컴포넌트에서 다른 컴포넌트로 전달할 수 있음.
이벤트 버스 형식
이벤트 버스를 구현하려면 별도의 뷰 인스턴스를 1개 더 생성하고, 새 인스턴스를 이용하여 이벤트를 보내고 받는다.
// 이벤트 버스를 위한 인스턴스 생성
var eventBus = new Vue();
// 이벤트를 보내는 컴포넌트
methods : {
메서드명 () {
eventBus.$emit("이벤트명", 데이터);
}
}
// 이벤트를 받는 컴포넌트
methods : {
메서드명 () {
eventBus.$on("이벤트명", function(데이터){
...
});
}
}
이벤트 버스를 활용하면 props 속성을 이용하지 않고도 원하는 컴포넌트 간에 직접적으로 데이터를 전달할 수 있어 편리하지만 컴포넌트가 많아지면 어디서 어디로 보냈는지 관리가 되지 않는 문제가 발생한다.
이 문제를 해결하려면 뷰엑스(Vuex)라는 상태 관리도구가 필요한데, 나중에 알아보도록하자....
'프로그래밍 노트 > Vue' 카테고리의 다른 글
Vuex란? (0) | 2019.10.17 |
---|---|
뷰(Vue) 라우터(Router) (0) | 2019.09.30 |
뷰(Vue) 컴포넌트(Component) (0) | 2019.09.24 |
뷰 라이프사이클 (Vue lifecycle) (1) | 2019.09.23 |
뷰(Vue) 인스턴스 (0) | 2019.09.23 |