컴포넌트
화면의 영역을 쪼개서 재사용 할 수 있는 형태로 만드는 기능(웹 화면을 헤더, 푸터, 컨텐츠영역, 네비 등으로 분할해서 화면을 구성한다고 생각하자)
전역 컴포넌트
먼저 전역 컴포넌트를 등록 해보자.
Vue.component('컴포넌트 이름', 컴포넌트 내용); 으로 등록 할 수 있다.
- js
Vue.component('global-component', { // 컴포넌트 이름은 케밥 형식이 아니여도 된다.
template: '<p>전역 컨텐츠의 내용이 요기잉네</p>'
});
const app = new Vue({
el : '#app'
});
- html
<div id="app">
<global-component></global-component> // 컴포넌트 이름과 같은 태그를 생성
</div>
전역 컴포넌트 렌더링 결과
지역 컴포넌트
지역 컴포넌트도 등록해보자.
전역컴포넌트랑 똑같은 방식인데 Vue 인스턴스 안에 넣어주면 된다.
※ 전역 컴포넌트는 Vue.component
이고, 지역 컴포넌트는 components
다. 복수형에 주의하자
- js
const app = new Vue({
el : '#app',
components: {
// '컴포넌트 이름' : 컴포넌트 내용
'local-component' : {
template: '<p>지역 컴포넌트 내용</p>'
}
}
});
- html
<div id="app">
<local-component></local-component>
</div>
지역 컴포넌트 렌더링 결과
지역 컴포넌트의 유효 범위
지역 컴포넌트의 유효범위는 해당 컴포넌트가 등록된 인스턴스 까지다.
여러개의 뷰 인스턴스가 있을 경우 차이를 느낄 수 있다.
뷰 인스턴스를 하나 더 만들어서 확인해보자.
- js
const app2 = new Vue({
el : '#app2',
components: {
'local-component' : {
template: '<p>이름은 같지만 다른 지역 컴포넌트</p>'
}
}
});
- html
<div id="app2">
<global-component></global-component>
<local-component></local-component>
</div>
컴포넌트 범위 테스트
유효범위가 이렇다보니 일반적인 개발 작업을 할 때는 지역 컴포넌트를 활용하고
플러그인이나 라이브러리를 개발할 때 전역 컴포넌트를 사용하게 된다.
See the Pen vue - Component by juein (@juein) on CodePen.
컴포넌트 통신
지역 컴포넌트 뿐 아니라, 모든 컴포넌트는 유효범위가 있다.
그리고 서로 다른 컴포넌트에서는 각각의 컴포넌트에서 정의된 데이터를 직접 참조하지 못한다.
const firstComponent = {
template: '<p>첫번째 컴포넌트에서 number : {{number}}</p>',
data: function(){
return{
number : 10
}
}
}
const secondComponent = {
template: '<p>두번째 컴포넌트에서 number : {{number}}</p>',
data: function(){
return{
number : 0 // 없으면 에러난다
}
}
}
const app = new Vue({
el: '#app',
components: {
'first-component' : firstComponent,
'second-component': secondComponent
}
});
See the Pen vue - Component-2 by juein (@juein) on CodePen.
이러한 컴포넌트의 유효범위는 불편해 보이지만 필요한 부분이다.
컴포넌트 내에서의 데이터가 모든 영역에서 공유될 경우
특정 컴포넌트의 변화로 인한 데이터 흐름을 추적하기 어려워지기 때문.
(규모가 큰 프로젝트면 디버깅의 헬이..)
이렇기에 뷰 컴포넌트의 데이터 전달 방법의 규칙은
위에서 아래로, 상위(부모) 컴포넌트 -> 하위(자식) 컴포넌트로 데이터를 전달하는 props방식이 있고,
하위(자식) 컴포넌트 -> 상위(부모) 컴포넌트로의 데이터 전달은 event를 발생시키는 방법이 있다.
상위, 하위 컴포넌트의 관계
※ 컴포넌트 간의 부모자식 관계는 별도로 등록하는것은 아니며
컴포넌트 등록시 Vue 인스턴스 자체가 상위(부모) 컴포넌트가 된다.
또는 템플릿에서 다른 컴포넌트를 사용하면 부모 자식 관계가 만들어진다.
// 자식 컴포넌트
const childComponent = {
};
// 부모 컴포넌트 (Root 컴포넌트)
const app = new Vue({
el : '#app',
components: {
'child-component': childComponent
}
});
뷰 개발자도구에서 부모 자식 관계를 한 눈에 확인 가능
또는 템플릿에서 컴포넌트를 사용하는 경우의 예
// 자식 컴포넌트
Vue.component('parent-component', {
template: '<div> <child-component></child-component> </div>'
});
// 자식의 자식 컴포넌트
Vue.component('child-component', {
template: '<div> 123 </div>'
})
// 부모 컴포넌트 (Root 컴포넌트)
const app = new Vue({
el : '#app',
});
props
컴포넌트의 부모 자식 관계에서 부모 -> 자식 에게 데이터를 전달하는 props의 사용법부터 알아보자.
- 부모 컴포넌트에서 데이터와 자식 컴포넌트 등록
const app = new Vue({
el : '#app',
data: {
parentData : '부모의 데이터를 자식 컴포넌트에서 호출하자'
},
components: {
'child-component': childComponent
}
});
- html 단에서 프롭스 속성명 / 상위 컴포넌트 이름 매칭
<div id="app">
<!-- v-bind:프롭스 속성 이름 = "상위 컴포넌트 데이터 이름"-->
<child-component v-bind:propsdata="parentData"></child-component>
</div>
- 자식 컴포넌트에서 props 속성으로 데이터 전달받기
//자식 컴포넌트
const childComponent = {
props: ['propsdata'],
template: '<p>{{propsdata}}</p>'
}
이렇게 props속성으로 받아온 데이터는 부모 컴포넌트의 데이터가 변경될 때
자식 컴포넌트에서의 데이터도 같이 변경된다. (reactivity, 반응성으로 되어있다.)
event
자식 -> 부모에게 데이터를 전달할때는 event를 발생시켜 값을 전달한다.
이벤트 발생과 수신은 $emit() 과 v-on 속성으로 구현한다.
- 자식 컴포넌트에서 이벤트 등록 (클릭 이벤트로 테스트 해보자)
const childComponent2 = {
template: '<input v-on:click="childClick" type="button" value="버튼"/>'
}
- 자식 컴포넌트에서 $emit 으로 컴포넌트에 연결되어 있는 이벤트를 명시적으로 실행시키기 (jquery의 trigger랑 비슷함)
methods: {
childClick: function(){
this.$emit('child-event'); //이벤트 발생
}
}
- html에서 child-event 이벤트가 발생하면 parentEvent를 호출 하도록 예약
<div id="app">
<!-- v-on:하위 컴포넌트 이벤트 이름="상위 컴포넌트 메소드 이름"-->
<child-component2 v-on:child-event="parentMethod"></child-component2>
</div>
- 부모 컴포넌트에서 이벤트 잡아서 실행
const app = new Vue({
el : '#app',
components: {
'child-component2': childComponent2
},
methods: {
parentMethod: function(){
console.log('부모 컴포넌트에서 이벤트 실행');
}
}
});
자식 컴포넌트에서 등록 된 버튼 클릭시, 부모 컴포넌트에서 지정된 함수가 실행되는걸 확인 할 수 있다.
See the Pen vue - props & event by juein (@juein) on CodePen.
이벤트 버스
이쯤 와서 재확인 해보자. 위에서 언급한 서로 다른 컴포넌트 의 관계는 부모 자식 관계가 아니다.
이처럼 부모 자식 관계가 아닌 컴포넌트는 props와 event로 데이터를 주고 받을 수 없기에 이벤트 버스 기능을 사용한다.
- 이벤트 버스 전용 인스턴스 만들기
var bus = new Vue();
- 값을 넘기고자 하는 컴포넌트에서 이벤트 발생시 eventBus 인스턴스를 이용한 $emit 으로 발생할 이벤트 명과 데이터를 전달
const firstComponent = {
template: '<p>첫번째 컴포넌트에서 number : {{number}} <button v-on:click="busEvent">값 넘기기</button></p>',
data: function(){
return{
number : 10
}
},
methods:{
busEvent: function(){
// 이벤트버스 인스턴스.$emit('발생할 이벤트 명', 전달 데이터);
bus.$emit('numberUpdate', this.number);
}
}
}
- 값을 받고자 하는 컴포넌트에서 eventBus 인스턴스의 이벤트를 $on 으로 수신
const secondComponent = {
template: '<p>두번째 컴포넌트에서 number : {{number}}</p>',
created: function(){
var self = this;
// 이벤트버스 인스턴스.$on('수신 이벤트 명', 수신 데이터)
// 이벤트 수신시 함수 처리도 가능
bus.$on('numberUpdate', function(value){
self.number = value;
});
},
data: function(){
return {
number : 0
}
}
}
See the Pen vue -eventBus by juein (@juein) on CodePen.
이벤트 버스는 편리하지만, 많이 사용하면 인스턴스와 이벤트가 꼬여서 코드가 복잡해진다.
'Web > Vue' 카테고리의 다른 글
[Vue] 반복 렌더링 & 조건 적용 (0) | 2020.08.04 |
---|---|
[Vue] 기본 기능 (0) | 2020.08.04 |
CentOS7 + Vue CLI 3.0 프로젝트 환경 구축 (0) | 2019.03.20 |
Vue devtools 활성화 문제 (0) | 2018.02.26 |
댓글