1. 뷰의 스코프(범위)
뷰의 경우 컴포넌트로 화면을 구성하므로 같은 웹 페이지라도 데이터를 공유할 수 없다.
그 이유는 컴포넌트마다 자체적으로 고유한 유효 범위를 갖기 때문이다.
뷰는 각 컴포넌트의 유효 범위가 독립적이기 때문에 다른 컴포넌트의 값을 직접적으로 참조할 수 없다.
쉽게 예제로 이해해보면
<div id="app">
<my-component1></my-component1>
<my-component2></my-component2>
</div>
my-component1, my-component2 2개의 컴포넌트를 등록하고 아래서 세팅해주었다.
<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>
첫번째 컴포넌트는 자신의 값을 가지고 세팅하였고, 두번째 컴포넌트 return 값은 첫번째 컴포넌트 값을 참조하였다.
출력해보면 결과는 첫번째 컴포넌트 값을 참조하였던 두번째 컴포넌트 값은 빈 값이다. 이유는 컴포넌트의 scope 때문에 my-component2 에서 my-component1을 직접 참조할 수 없기 때문이다.
2. 데이터 주고 받기
1) props 속성
- 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달할 때 사용하는 속성
* 뷰에서 상위 컴포넌트와 하위 컴포넌트의 개념??
-> 이는 컴포넌트를 등록함과 동시에 뷰 인스턴스 자체가 상위 컴포넌트가 되기 때문
즉, 기존에 있는 인스턴스에 새로운 컴포넌트를 등록하면 기존에 컴포넌트는 상위 컴포넌트가 되고,
새로 등록된 컴포넌트는 하위 컴포넌트가 된다. 이렇게 새 컴포넌트를 등록한 인스턴스를 최상위 컴포넌트 즉, root component 라고 한다.
<child-component v-bind:props 속성 이름="상위 컴포넌트의 data 속성"></child-component>
Vue.component('child-component', {
props: ['props 속성 이름']
});
하단 소스 참조하여 처리되는 순서
1. new Vue()로 인스턴스 하나 생성
2. Vue.component()를 이용하여 child-component 등록
3. child-component의 내용에 props 속성으로 propsdata를 정의
4. <child-component> 태그의 v-bind 속성을 보면 v-bind:propsdata="message" 상위 컴포넌트의 message 속성 값 'Hello Vue!' 텍스트를 하위 컴포넌트인 propsdata로 전달
5. {{ propsdata }} 는 위에서 넘겨받은 값은 'Hello Vue!'로 치환
<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>
결론 : 뷰 인스턴스의 data 속성에 정의된 message 속성값을 하위 컴포넌트에 props로 전달
2) 이벤트 발생과 수신
props는 상위에서 하위 컴포넌트로 데이터를 전달하는 방식이었다면, $emit()은 이벤트를 발생시켜 상위 컴포넌트에 신호를 보내는 속성
- $emit() : 이벤트 발생 속성
- v-on: : 이벤트 수신 속성
// 이벤트 발생
this.$emit('이벤트명');
// 이벤트 수신
<child-component v-on:이벤트명="상위 컴포넌트의 메서드명"></child-component>
이벤트 발생시킬 때의 this는 하위 컴포넌트를 가르킨다.
하단 소스 참조하여 처리되는 순서
1. [show] 버튼 클릭하면 클릭이벤트 v-on:click="showLog"에 따라 showLog() 실행
2. showLog() 메서드 안에 this.$emit('show-log') 실행되면서 show-log 이벤트 발생
3. show-log 이벤트는 <child-component>에 정의한 v-on:show-log에 전달되고, v-on:show-log의 대상 메서드인 최상위 컴포넌트의 메서드 printText() 실행
4. printText() 메서드 안에 console.log 내용인 'received an event' 출력
<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>
결론 : .$emit()으로 이벤트를 발생시키고, v-on으로 이벤트를 받는다.
3) 이벤트 버스 (EventBus)
1), 2) 에서는 상.하위 컴포넌트 간의 데이터 주고받기 내용이었다면, 이벤트 버스는 관계없는 컴포넌트 간의 통신을 말한다.
- .$emit() : 이벤트 발생 속성
- .$on() : 이벤트 수신 속성
// 이벤트 버스를 위한 추가 인스턴스 1개 생성
var eventBus = new Vue();
// 이벤트를 보내는 컴포넌트
methods: {
메서드명 : function(){
eventBus.$emit('이벤트명', 데이터);
}
}
// 이벤트를 받는 컴포넌트
methods: {
created : function(){
eventBus.$on('이벤트명', function( 데이터 ){
});
}
}
하단 소스 참조하여 처리되는 순서
1. 먼저 이벤트 버스로 활용할 새 인스턴스를 1개 생성하고 eventBus라는 변수에 참조한다. 이제 eventBus변수로 새 인스턴스의 속성과 메서드에 접근 가능
2. template 속성에는 '하위 컴포넌트 영역입니다. 라는 텍스트와 [show] 버튼을 추가.
3. methods 속성에는 showLog() 메서드 정의하고, 메서드 안에는 eventBus.$emit()을 선언.
triggerEventBus라는 이벤트를 발생하는 로직을 추가하고, 이벤트가 발생할 때 수신하는 쪽에 100이라는 값을 함께 전달
4. 상위 컴포넌트의 created 라이프 사이클 훅에 eventBus.$on()으로 이벤트를 받는 로직을 선언
발생한 이벤트 triggerEventBus를 수신할 때 value로 앞에서 전달되는 인자 값 100을 받아 콘솔에 출력
<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>
* Do it! Vue.js 입문 책으로 공부하며 작성하는 글로 잘못된 정보가 있을 경우 댓글 달아주시면 감사하겠습니다 : )
'Vue.js' 카테고리의 다른 글
[Vue.js] 각종 태그 데이터 바인딩 하기 (0) | 2021.09.17 |
---|---|
[Vue.js] 웹 앱 HTTP 통신, 라우터 (0) | 2021.09.08 |
[Vue.js] 뷰 컴포넌트란? | 전역 컴포넌트 | 지역 컴포넌트 (0) | 2021.09.06 |
[Vue.js] 뷰 인스턴스 생명주기 | 라이프 사이클 (0) | 2021.09.05 |
[Vue.js] 뷰 인스턴스, 생성자, 옵션 속성 (0) | 2021.09.04 |