컴포넌트 간 통신과 유효 범위
Vue.js는 컴포넌트로 화면을 구성한다.
각 컴포넌트마다 자체적으로 고유한 유효 범위(Scope)를 갖고 있고, 때문에 같은 웹 페이지라도 데이터를 공유할 수 없다. 이는 뷰 프레임 워크 내부적으로 정의된 특징으로, 각 컴포넌트의 유효 범위가 독립적이기 때문에 다른 컴포넌트의 값을 직접적으로 참조할 수 없다.
#예제 1
<html>
<head>
<title>Vue sample</title>
</head>
<body>
<div id="app">
<h3>app 영역</h3>
<my-component1></my-component1>
<my-component2></my-component2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
<script>
//첫번째 컴포넌트 등록
var cmp1 = {
template: '<div>첫번째 지역 컴포넌트 : {{ cmp1Data }}</div>',
data: function() {
return {
cmp1Data : 100
}
}
};
//두번째 컴포넌트 등록
var cmp2 = {
template: '<div>두번째 지역 컴포넌트 : {{ cmp2Data }}</div>',
data: function() {
return {
cmp2Data : cmp1.data.cmp1Data
}
}
};
new Vue({
el:'#app',
//지역 컴포넌트 등록
components: {
'my-component1': cmp1,
'my-component2': cmp2
}
});
</script>
</body>
</html>
cmp1과 cmp2 지역 컴포넌트를 등록하고, cmp2 컴포넌트에서 cmp1 컴포넌트의 data.cmp1Data 값을 직접 참조했을 때, 값이 나오지 않는걸 확인할 수 있다.
상위 컴포넌트와 하위 컴포넌트
앞서 [Do it! Vue.js 입문] 04. 뷰 컴포넌트에서 다룬 컴포넌트 등록 방법으로 지역, 전역 컴포넌트를 등록하면 자연스럽게 하위 컴포넌트가 되고고 하위 컴포넌트를 등록한 인스턴스는 상위 컴포넌트가 된다.
props 속성 : 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달 할 때 사용하는 속성
하위 컴포넌트의 props 속성 정의 방식
Vue.component('컴포넌트 이름', {
props: ['props 속성 이름']
});
상위 컴포넌트 HTML 코드
<컴포넌트 이름 v-bind:props 속성 이름="상위 컴포넌트의 data 속성"></컴포넌트 이름>
#예제 2
뷰 인스턴스의 data 속성에 정의된 message 속성을 하위 컴포넌트에 props로 전달하여 화면에 나타내는 코드이다.
<html>
<head>
<title>Vue sample</title>
</head>
<body>
<div id="app">
<!-- 팁 : 오른쪽에서 왼쪽으로 속성을 읽으면 더 수월합니다. ex) message를 propsdata에 대입 -->
<child-component v-bind:propsdata="message"></child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
<script>
Vue.component('child-component', {
props: ['propsdata'],
template: '<p>{{ propsdata }}</p>'
});
new Vue({
el:'#app',
//지역 컴포넌트 등록
data: {
message : 'Hello Vue! passed from Parent component'
}
});
</script>
</body>
</html>
코드를 살펴보자면,
1. new Vue()로 인스턴스 생성
2. Vue.component()로 하위 컴포넌트인 child-component를 등록
3. child-component의 내용에 props 속성으로 propsdata를 정의
4. HTML에 컴포넌트 태그를 추가.
v-bind:propsdata="message"는 상위 컴포넌트의 message 속성 값을 하위 컴포넌트의 propsdata로 전달.
5. child-component의 propsdata에 message값이 전달되었으니,
최종적으로 template: '<p>{{ propsdata}}</p>'는 '<p>Hello Vue! passed from Parent component</p>'이 됨
인스턴스에 새로운 컴포넌트를 등록하면 기존에 있는 컴포넌트는 상위 컴포넌트(부모)가 되고, 새로 등록된 컴포넌트는 하위(자식) 컴포넌트가 된다. 이렇게 새 컴포넌트를 등록한 인스턴스를 최상위 컴포넌트(Root Component)라고도 부른다.
(* 하위에서 상위 컴포넌트로 데이터를 전달은 뷰의 단방향 데이터 흐름에 어긋나는 구현 방법으로 뷰 공식 사이트에서 따로 방법을 다루지 않는다. 다만 복작합 뷰 애플리케이션을 구축할 때 이벤트 버스(Event Bus)를 이용해 데이터를 전달하는 방식을 사용한다. 추후 이벤트 버스에 대해 다룰때 언급)
하위에서 상위 컴포넌트로 이벤트 전달하기
하위에서 상위 컴포넌트로 통신을 할 때는 이벤트를 발생(event emit)시켜 상위 컴포넌트에 신호를 보낸다.
상위 컴포넌트에서 하위 컴포넌트의 특정 이벤트가 발생하기를 기다리고 있다가, 이벤트가 발생하면 해당 이벤트를 수신하여 상위 컴포넌트의 메서드를 호출한다.
<!-- 이벤트 발생, $emit()을 이용한 이벤트 발생 -->
this.$emit('이벤트명');
<!-- 이벤트 수신, v-on : 속성을 이용한 이벤트 수신 -->
<child-component v-on:이벤트명="상위 컴포넌트의 메서드명"></child-component>
이벤트명에 입력한 특정 이벤트가 발생하면, 상위 컴포넌트의 메서드명에 입력한 메서드가 실행되고,
$emit()가 호출되면 괄호 안에 정의된 이벤트가 발생한다.
#예제 3
child-component의 show 버튼을 클릭하여 이벤트를 발생시키고(클릭 이벤트), 발생한 이벤트로 상위 컴포넌트(여기선 루트 컴포넌트)의 printText() 메서드를 실행시킨다.
<html>
<head>
<title>Vue sample</title>
</head>
<body>
<div id="app">
<child-component v-on:show-log="printText"></child-component>
<!-- show-log 하위 컴포넌트의 이벤트 명, printText 상위 컴포넌트의 메서드명 -->
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
<script>
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>
1. show 버튼을 클릭하면 클릭 이벤트 v-on:click="showLog"에 따라 showLog() 메서드가 실행
2. this.$emit('show-log')을 호출하면 괄호 안에 정의된 show-log 이벤트가 발생
3. v-on:show-log의 대상 메서드인 최상위 컴포넌트의 메서드 printText()가 실행
4. printText()가 실행되면서 콘솔에 로그 received an event가 출력
'JavaScript > Vue.js' 카테고리의 다른 글
[Do it! Vue.js 입문] 08. 뷰 HTTP 통신 - 뷰 리소스, 액시오스 (Vue Resource, Axios) (0) | 2021.09.02 |
---|---|
[Do it! Vue.js 입문] 07. 뷰 라우터 (네스티드 라우터, 네임드 뷰) (0) | 2021.09.01 |
[Do it! Vue.js 입문] 06. 이벤트 버스 (0) | 2021.08.12 |
이클립스 Spring 프로젝트에서 Vue.js 사용하기 (0) | 2021.08.06 |
[Do it! Vue.js 입문] 04. 뷰 컴포넌트 (0) | 2021.08.02 |
[Do it! Vue.js 입문] 03. 뷰 인스턴스 (0) | 2021.08.02 |
[Do it! Vue.js 입문] 02. Vue.js 시작하기 (0) | 2021.07.30 |