뷰의 경우 컴포넌트로 화면을 구성하므로 같은 웹 페이지라도 데이터를 공유할 수 없다.
그 이유는 컴포넌트마다 자체적으로 고유한 유효 범위를 갖기 때문인데 뷰는 각 컴포넌트의 유효 범위가 독립적이기 때문에 다른 컴포넌트의 값을 직접적으로 참조할 수 없다.
ex)
<div id="app">
<my-component1></my-component1>
<my-component2></my-component2>
</div>
<script>
//첫번째 컴포넌트
const cmp1 = {
template : '<div>첫 번째 지역 컴포넌트 : {{ cmp1Data }}</div>',
data : function(){
return {
cmp1Data : 100
}
}
};
//2번째 컴포넌트
const cmp2 = {
template : '<div>두 번째 지역 컴포넌트 : {{ cmp2Data }}</div>',
data : function(){
return {
cmp2Data : cmp1.data.cmp1Data
}
}
};
new Vue({
el : '#app',
components : {
'my-component1' : cmp1,
'my-component2' : cmp2
}
});
</script>
첫번째 지역 컴포넌트 : 100
두번째 지역 컴포넌트 :
출력을 해보면 첫번째 컴포넌트 값을 참조하였던 두번째 값은 빈 값이다.
이유는 컴포넌트의 scope 때문에 2가 1을 직접 참조가 불가능 하기 때문이다.
컴포넌트 관계도에서 상-하 관계에 있는 컴포넌트 통신은
<child-component v-bind:props 속성 이름="상위 컴포넌트의 data 속성"></child-component>
Vue.component('child-component', {
props: ['props 속성 이름']
});
<div id="app">
// 4
<child-component v-bind:propsdata="message"></child-component>
</div>
<script>
// 2
Vue.component('child-component', {
// 3
props : ['propsdata'],
// 5
template : '<p> {{ propsdata }}</p>'
});
// 1
new Vue({
el : '#app',
data : {
message : 'Hello Vue!'
}
});
</script>
동일한 상위 컴포넌트를 가진 하위 컴포넌트들 간의 통신은 아래와 같이 해야 한다.
// 이벤트 발생
this.$emit('이벤트명');
// 이벤트 수신
<child-component v-on:이벤트명="상위 컴포넌트의 메서드명"></child-component>
이벤트 발생시킬 때의 this는 하위 컴포넌트를 가르킨다.
<div id="app">
// 3
<child-component v-on:show-log="printText"></child-component>
</div>
<script>
Vue.component('child-component', {
// 1
template : '<button v-on:click="showLog">show</button>',
// 2
methods: {
showLog : function(){
this.$emit('show-log');
}
}
});
const app = new Vue({
el : '#app',
data : {
message : 'Hello, Vue'
},
methods : {
// 4
printText : function(){
console.log("received an event");
}
}
});
</script>
[show] 버튼을 클릭하면 클릭이벤트 v-on:click="showLog"에 따라 showLog() 실행
showLog() 메서드 안에 this.$emit('show-log') 실행되면서 show-log 이벤트 발생
show-log 이벤트는 에 정의한 v-on:show-log에 전달되고, v-on:show-log의 대상 메서드인 최상위 컴포넌트의 메서드 printText() 실행
printText() 메서드 안에 console.log 내용인 'received an event' 출력
결론 : .$emit()으로 이벤트를 발생시키고, v-on으로 이벤트를 받는다.
// 이벤트 버스를 위한 추가 인스턴스 1개 생성
var eventBus = new Vue();
// 이벤트를 보내는 컴포넌트
methods: {
메서드명 : function(){
eventBus.$emit('이벤트명', 데이터);
}
}
// 이벤트를 받는 컴포넌트
methods: {
created : function(){
eventBus.$on('이벤트명', function( 데이터 ){
});
}
}
<div id="app">
<child-component></child-component>
</div>
<script>
// 1
var eventBus = new Vue();
Vue.component('child-component', {
// 2
template : '<div>하위 컴포넌트 영역입니다. <button v-on:click="showLog">show</button></div>',
// 3
methods : {
showLog : function(){
eventBus.$emit('triggerEventBus', 100);
}
}
});
var app = new Vue ({
el : '#app',
created : function(){
// 4
eventBus.$on('triggerEventBus', function(value){
console.log("이벤트를 전달받음. 전달받은 값 : ", value);
});
}
});
</script>
뷰의 컴포넌트는 자체적으로 고유한 독립을 가지기 때문에 다른 컴포넌트를 참조할 수 없다는게 좀 충격이었다.
그래서 그 서로간에 참조를 할 수 있는 방법을 공부해보았는데, 공부를 하며 아직 이해되지 않는 부분이 꽤 있었다.
위에서 아래로, 아래에서 위로 서로 통신하는데 각기 다른 방법을 사용을 하는것도 Vue.js를 공부하며 이런 방식을 쓰는구나 라고 생각을 하며 자바만을 공부했던 나에게 아직 컴퓨터 언어의 세상은 넒고 나의 지식은 매우 좁구나라고 느꼈다.