컴포넌트의 통신 방식
뷰 컴포넌트는 각 각 고유한 데이터 유효 범위를 갖는다. 따라서, 컴포넌트 간에 데이터를 주고 받기 위해선 아래와 같은 규칙을 따라야 한다.
- 상위에서 하위로 데이터 전달 : Props 속성
- 하위에서 상위로 이벤트 전달 : 이벤트 발생
Props 속성
프롭스 속성은 컴포넌트 간에 데이터를 전달할 수 있는 컴포넌트 통신 방법 중 하나이다. 속성을 기억할 때는 상위 컴포넌트에서 하위 컴포넌트로 내려보내는 데이터 속성으로 기억하면 쉽다.
프롭스 속성을 이용할 때는 "디렉티브"를 이용하여, 상/하위 컴포넌트 모두에 각 각 코드를 추가해줘야 한다.
<body>
<div id="app">
<app-header v-bind:propsdata="message"></app-header>
<app-content v-bind:propsdata="num"></app-content>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var appHeader = {
template : "<h1>{{propsdata}}</h1>",
props: ["propsdata"]
};
var appContent = {
template : "<div>{{propsdata}}</div>",
props : ["propsdata"]
}
new Vue({
el: "#app",
components:{
"app-header" : appHeader,
"app-content" : appContent
},
data:{
message : "hi",
num: 10
}
});
</script>
</body>
해당 구문은 두 개의 컴포넌트로 구성되어 있고, 각 각의 컴포넌트는 서로 다른 Props를 가진다.
이전에 JS에 관해 공부를 할 때 SCOPE라는 개념에 대해 이해를 했다. 컴포넌트도 스코프의 개념과 동일하게
서로 영향을 주지 않아, 내부 Props의 명칭을 동일하게 주고 사용해도 영향을 주지 않는다.
단, bind 할 대상이 ID / CLASS일 경우 Data 속성의 값을 설정할 때는 주의를 해야한다. 스타일 속성이나 스크립트 기능의 중복의 우려가 있다.
각 컴포넌트에 대한 props 명을 받아, vue 속성의 값을 따로 받으면 아래와 같이 값을 출력한다.
전체 root 가 가지고 있는 data 속성의 값
app-header 컴포넌트가 가지고 있는 데이터 ( propsdata로 message 값이 할당 )
app-content 컴포넌트가 가지고 있는 데이터 ( propsdata로 num 값이 할당 )
Event Emit
앞서 컴포넌트의 통신 방식은 상위에서 하위로, 하위에서 상위로 전달하는 방식이 있다. Event Emit은 하위에서 상위로 이벤트를 전달하는 방식이다.
이벤트 발생 코드 형식
Event Emit 도 Props 방식과 동일하게 상위 / 하위 모두 코드를 작성해줘야 한다.
// 하위 컴포넌트의 내용
this.$emit('이벤트 명');
<!-- 상위 컴포넌트의 템플릿 -->
<div id="app">
<child-component v-on:이벤트 명="상위 컴포넌트의 실행할 메서드 명 또는 연산"></child-component>
</div>
props의 경우는 v-bind를 사용했지만, emit의 경우는 v-on을 사용하여 이벤트 명을 지정한다.
<div id="app">
<p>{{num}}</p>
<app-header v-on:pass="logText"></app-header>
<app-content v-on:increase="increaseNumber"></app-content>
</div>
HTML 파일의 예시이다. 해당 예시는 NUM이라는 초기 값에 pass를 누르면 하위와 상위 가 어떤 순서로 출력되는지에 대해 console에 출력하고, increase 는 num을 1씩 증가시킨다.
그리고 아래는 뷰 인스턴스이다.
new Vue({
el: "#app",
components : {
"app-header" : appHeader,
"app-content" : appContent
},
methods : {
logText : function(){
console.log("상위 컴포넌트 실행");
},
increaseNumber : function(){
this.num = this.num + 1;
}
},
data : {
num : 10
}
});
<script>
var appHeader = {
template : "<button v-on:click='passEvent'>click me</button>",
methods:{
passEvent : function(){
this.$emit("pass");
console.log("하위 컴포넌트 실행");
}
}
}
var appContent = {
template : "<button v-on:click='addNumber'>add</button>",
methods : {
addNumber : function(){
this.$emit("increase");
console.log("increase 실행");
}
},
props : ["propsNum"]
}
new Vue({
el: "#app",
components : {
"app-header" : appHeader,
"app-content" : appContent
},
methods : {
logText : function(){
console.log("상위 컴포넌트 실행");
},
increaseNumber : function(){
this.num = this.num + 1;
}
},
data : {
num : 10
}
});
</script>
스크립트 구문의 경우 2개의 컴포넌트, app-header와 app-content로 구성되어 있다.
app-header
var appHeader = {
template : "<button v-on:click='passEvent'>click me</button>",
methods:{
passEvent : function(){
this.$emit("pass");
console.log("하위 컴포넌트 실행");
}
}
}
appHeader 컴포넌트의 구성을 template에 button에 passEvent가 설정되어 있다.
passEvent의 경우, appHeader 컴포넌트 내부 속성인 methods 부분에서 설정이 가능하다.
이때 this(=appHeader)의 $emit을 사용하여 이벤트의 이름을 "pass" 라고 지정한다.
이렇게 구성된 pass 이벤트명을 위 app-header 태그의 v-on에서 pass로 받아 사용한다.
대상 이벤트는 app-header 컴포넌트를 지정하는 app Header 내에 지정됐기 때문에
app-content에서 사용하면 사용이 되지 않는다.
app-content
var appContent = {
template : "<button v-on:click='addNumber'>add</button>",
methods : {
addNumber : function(){
this.$emit("increase");
console.log("increase 실행");
}
},
props : ["propsNum"]
}
appContent 컴포넌트의 경우에도 app-header와 비슷하게 구성되어 있다.
그리고 위를 보면 vue 인스턴스에 내의 메소드가를 통해 각 각의 컴포넌트에서 메서드를 따로 따로 실행시킨다.
'Programming > Vue' 카테고리의 다른 글
[Vue] 라우터 ( Router ) (0) | 2024.06.25 |
---|---|
[Vue] 템플릿 문법과 컴포넌트(component) (0) | 2024.06.25 |
[Vue] Vue & 인스턴스 (0) | 2024.06.25 |